Oom_recreation.sql
text/plain
Filename: Oom_recreation.sql
Type: text/plain
Part: 0
CREATE TABLE pg_temp.parts
(
seid bigint,
r_field_name_1 smallint,
fr_field_name smallint NOT NULL,
p1_field_name varchar(4),
qty_field_name integer,
p5_field_name varchar(30),
partnum varchar(30),
st_field_name smallint DEFAULT 0 NOT NULL
); -- drop table pg_temp.parts;
INSERT INTO pg_temp.parts (seid, partnum, qty_field_name, fr_field_name, st_field_name)
SELECT (RANDOM() * 3821 + 1)::bigint AS seid,
(RANDOM() * 123456789)::text AS partnum,
CASE
WHEN q.rnd BETWEEN 0 AND 0.45 THEN FLOOR(RANDOM() * 900) + 100 -- Random number in the range [100, 999]
WHEN q.rnd BETWEEN 0.46 AND 0.96 THEN LEAST(TRUNC(FLOOR(RANDOM() * 999999) + 1000)::int, 999999::int) -- Random number in the range [1000, 9999]
ELSE FLOOR(RANDOM() * 9000000) + 1000000 -- Random number in the range [100000, 999999]
END AS qty_field_name,
CASE WHEN RANDOM() < 0.72 THEN 0::smallint ELSE 1::smallint END AS fr_field_name,
CASE WHEN RANDOM() < 0.46 THEN 1::smallint ELSE 2::smallint END AS st_field_name
FROM (SELECT RANDOM() AS rnd, x FROM GENERATE_SERIES(1, 90_000_000) x) q;
CREATE INDEX idx_parts_supid ON pg_temp.parts USING btree (seid, p1_field_name, partnum, st_field_name, r_field_name_1, qty_field_name);
CREATE INDEX idx_parts_p5 ON pg_temp.parts USING btree (p5_field_name, seid, st_field_name, r_field_name_1, p1_field_name);
CREATE INDEX idx_parts_partnum ON pg_temp.parts USING btree (partnum, seid, st_field_name, r_field_name_1, p1_field_name);
CREATE OR REPLACE FUNCTION pg_temp.fx(asupplier bigint = 497 )
RETURNS void
LANGUAGE plpgsql
AS
$function$
DECLARE
supplier_parts CURSOR (sid bigint) FOR -- Again, selecting with COUNT() would reduce 1 query per row!
SELECT
partnum, qty_field_name, st_field_name, sum(qty_field_name) as qty
FROM pg_temp.parts
WHERE seid = sid AND (st_field_name = 1)
GROUP BY partnum, qty_field_name, st_field_name
ORDER BY partnum, qty_field_name, st_field_name;
supplier_part_qty_matches CURSOR (sid bigint, pnum varchar(30), pqty bigint) FOR
SELECT DISTINCT
seid, fr_field_name, partnum, st_field_name
FROM pg_temp.parts
WHERE seid <> sid AND partnum = pnum AND qty_field_name = pqty
ORDER BY seid, partnum;
a_partnum varchar(30);
a_qty integer;
a_st smallint;
a_cnt integer = 0;
b_partnum varchar(30);
b_fr smallint;
b_seid bigint;
b_st smallint;
b_cnt bigint = 0;
BEGIN
RAISE NOTICE '%', (SELECT (PG_SIZE_PRETTY(SUM(used_bytes)), PG_SIZE_PRETTY(SUM(total_bytes)), PG_SIZE_PRETTY(SUM(free_bytes))) FROM pg_get_backend_memory_contexts());
OPEN supplier_parts (asupplier);
LOOP
FETCH supplier_parts INTO a_partnum, a_qty, a_st, a_qty;
EXIT WHEN NOT FOUND;
a_cnt := a_cnt + 1;
OPEN supplier_part_qty_matches (sid := asupplier, pnum := a_partnum, pqty := a_qty);
LOOP
FETCH supplier_part_qty_matches INTO b_seid, b_fr, b_partnum, b_st;
b_cnt := b_cnt + 1;
EXIT WHEN TRUE; -- no Need to loop here One FETCH per query triggers the losses.
END LOOP;
CLOSE supplier_part_qty_matches;
END LOOP;
CLOSE supplier_parts;
RAISE NOTICE '-----------after close, Count a: %, count b: %', a_cnt, b_cnt;
RAISE NOTICE '%', (SELECT (PG_SIZE_PRETTY(SUM(used_bytes)), PG_SIZE_PRETTY(SUM(total_bytes)), PG_SIZE_PRETTY(SUM(free_bytes))) FROM pg_get_backend_memory_contexts());
--perform meminfo();
END;
$function$;
-- This will use JIT until the table is analyzed, which causes the problem
explain SELECT DISTINCT seid, fr_field_name, st_field_name
FROM pg_temp.parts
WHERE seid <> 497 AND partnum >= '1'
ORDER BY seid;
-- But using JIT results in loss of some bytes.
SELECT pg_temp.fx(497);