-- only use parallelism when explicitly intending to do so SET max_parallel_maintenance_workers = 0; SET max_parallel_workers = 0;
-- A table with contents that, when sorted, triggers abbreviated -- key aborts. One easy way to achieve that is to use uuids that all -- have the same prefix, as abbreviated keys for uuids just use the -- first sizeof(Datum) bytes. CREATE TEMP TABLE abbrev_abort_uuids (
id serial notnull,
abort_increasing uuid,
abort_decreasing uuid,
noabort_increasing uuid,
noabort_decreasing uuid);
-- and a few NULLs INSERTINTO abbrev_abort_uuids(id) VALUES(0); INSERTINTO abbrev_abort_uuids DEFAULTVALUES; INSERTINTO abbrev_abort_uuids DEFAULTVALUES;
-- add just a few duplicates INSERTINTO abbrev_abort_uuids (abort_increasing, abort_decreasing, noabort_increasing, noabort_decreasing) SELECT abort_increasing, abort_decreasing, noabort_increasing, noabort_decreasing FROM abbrev_abort_uuids WHERE (id < 10OR id > 19990) AND id % 3 = 0AND abort_increasing isnotnull;
-- plain sort triggering abbreviated abort SELECT abort_increasing, abort_decreasing FROM abbrev_abort_uuids ORDERBY abort_increasing OFFSET 20000 - 4; SELECT abort_increasing, abort_decreasing FROM abbrev_abort_uuids ORDERBY abort_decreasing NULLS FIRST OFFSET 20000 - 4;
-- plain sort not triggering abbreviated abort SELECT noabort_increasing, noabort_decreasing FROM abbrev_abort_uuids ORDERBY noabort_increasing OFFSET 20000 - 4; SELECT noabort_increasing, noabort_decreasing FROM abbrev_abort_uuids ORDERBY noabort_decreasing NULLS FIRST OFFSET 20000 - 4;
-- bounded sort (disables abbreviated keys) SELECT abort_increasing, noabort_increasing FROM abbrev_abort_uuids ORDERBY abort_increasing LIMIT5; SELECT abort_increasing, noabort_increasing FROM abbrev_abort_uuids ORDERBY noabort_increasing NULLS FIRST LIMIT5;
---- -- Check index creation uses of tuplesort wrt. abbreviated keys ----
-- index creation using abbreviated keys successfully CREATEINDEX abbrev_abort_uuids__noabort_increasing_idx ON abbrev_abort_uuids (noabort_increasing); CREATEINDEX abbrev_abort_uuids__noabort_decreasing_idx ON abbrev_abort_uuids (noabort_decreasing);
-- index creation using abbreviated keys, hitting abort CREATEINDEX abbrev_abort_uuids__abort_increasing_idx ON abbrev_abort_uuids (abort_increasing); CREATEINDEX abbrev_abort_uuids__abort_decreasing_idx ON abbrev_abort_uuids (abort_decreasing);
-- when aborting, increasing order
BEGIN; SET LOCAL enable_indexscan = false;
CLUSTER abbrev_abort_uuids USING abbrev_abort_uuids__abort_increasing_idx;
-- head SELECT id, abort_increasing, abort_decreasing, noabort_increasing, noabort_decreasing FROM abbrev_abort_uuids ORDERBY ctid LIMIT5;
-- when aborting, decreasing order
BEGIN; SET LOCAL enable_indexscan = false;
CLUSTER abbrev_abort_uuids USING abbrev_abort_uuids__abort_decreasing_idx;
-- head SELECT id, abort_increasing, abort_decreasing, noabort_increasing, noabort_decreasing FROM abbrev_abort_uuids ORDERBY ctid LIMIT5;
-- when not aborting, increasing order
BEGIN; SET LOCAL enable_indexscan = false;
CLUSTER abbrev_abort_uuids USING abbrev_abort_uuids__noabort_increasing_idx;
-- head SELECT id, abort_increasing, abort_decreasing, noabort_increasing, noabort_decreasing FROM abbrev_abort_uuids ORDERBY ctid LIMIT5;
-- when no aborting, decreasing order
BEGIN; SET LOCAL enable_indexscan = false;
CLUSTER abbrev_abort_uuids USING abbrev_abort_uuids__noabort_decreasing_idx;
-- head SELECT id, abort_increasing, abort_decreasing, noabort_increasing, noabort_decreasing FROM abbrev_abort_uuids ORDERBY ctid LIMIT5;
-- Ensure the order is correct and values look intact SELECTLEFT(a,10),b FROM
(VALUES(REPEAT('a', 512 * 1024),1),(REPEAT('b', 512 * 1024),2)) v(a,b) ORDERBY v.a DESC;
---- -- test forward and backward scans for in-memory and disk based tuplesort ----
-- in-memory
BEGIN; SET LOCAL enable_indexscan = false; -- unfortunately can't show analyze output confirming sort method, -- the memory used output wouldn't be stable EXPLAIN (COSTS OFF) DECLARE c SCROLL CURSORFORSELECT noabort_decreasing FROM abbrev_abort_uuids ORDERBY noabort_decreasing; DECLARE c SCROLL CURSORFORSELECT noabort_decreasing FROM abbrev_abort_uuids ORDERBY noabort_decreasing;
-- first and second FETCH NEXT FROM c; FETCH NEXT FROM c;
-- scroll beyond beginning FETCH BACKWARD FROM c; FETCH BACKWARD FROM c; FETCH BACKWARD FROM c; FETCH BACKWARD FROM c; FETCH NEXT FROM c;
-- scroll beyond end FETCH LAST FROM c; FETCH BACKWARD FROM c; FETCH NEXT FROM c; FETCH NEXT FROM c; FETCH NEXT FROM c; FETCH BACKWARD FROM c; FETCH NEXT FROM c;
COMMIT;
-- disk based
BEGIN; SET LOCAL enable_indexscan = false; SET LOCAL work_mem = '100kB'; -- unfortunately can't show analyze output confirming sort method, -- the memory used output wouldn't be stable EXPLAIN (COSTS OFF) DECLARE c SCROLL CURSORFORSELECT noabort_decreasing FROM abbrev_abort_uuids ORDERBY noabort_decreasing; DECLARE c SCROLL CURSORFORSELECT noabort_decreasing FROM abbrev_abort_uuids ORDERBY noabort_decreasing;
-- first and second FETCH NEXT FROM c; FETCH NEXT FROM c;
-- scroll beyond beginning FETCH BACKWARD FROM c; FETCH BACKWARD FROM c; FETCH BACKWARD FROM c; FETCH BACKWARD FROM c; FETCH NEXT FROM c;
-- scroll beyond end FETCH LAST FROM c; FETCH BACKWARD FROM c; FETCH NEXT FROM c; FETCH NEXT FROM c; FETCH NEXT FROM c; FETCH BACKWARD FROM c; FETCH NEXT FROM c;
COMMIT;
---- -- test tuplesort using both in-memory and disk sort ---
-- memory based SELECT -- fixed-width by-value datum
(array_agg(id ORDERBY id DESC NULLS FIRST))[0:5], -- fixed-width by-ref datum
(array_agg(abort_increasing ORDERBY abort_increasing DESC NULLS LAST))[0:5], -- variable-width datum
(array_agg(id::text ORDERBY id::text DESC NULLS LAST))[0:5], -- fixed width by-value datum tuplesort
percentile_disc(0.99) WITHIN GROUP (ORDERBY id), -- ensure state is shared
percentile_disc(0.01) WITHIN GROUP (ORDERBY id), -- fixed width by-ref datum tuplesort
percentile_disc(0.8) WITHIN GROUP (ORDERBY abort_increasing), -- variable width by-ref datum tuplesort
percentile_disc(0.2) WITHIN GROUP (ORDERBY id::text), -- multi-column tuplesort
rank('00000000-0000-0000-0000-000000000000', '2', '2') WITHIN GROUP (ORDERBY noabort_increasing, id, id::text) FROM ( SELECT * FROM abbrev_abort_uuids UNIONALL SELECTNULL, NULL, NULL, NULL, NULL) s;
-- disk based (see also above)
BEGIN; SET LOCAL work_mem = '100kB';
SELECT
(array_agg(id ORDERBY id DESC NULLS FIRST))[0:5],
(array_agg(abort_increasing ORDERBY abort_increasing DESC NULLS LAST))[0:5],
(array_agg(id::text ORDERBY id::text DESC NULLS LAST))[0:5],
percentile_disc(0.99) WITHIN GROUP (ORDERBY id),
percentile_disc(0.01) WITHIN GROUP (ORDERBY id),
percentile_disc(0.8) WITHIN GROUP (ORDERBY abort_increasing),
percentile_disc(0.2) WITHIN GROUP (ORDERBY id::text),
rank('00000000-0000-0000-0000-000000000000', '2', '2') WITHIN GROUP (ORDERBY noabort_increasing, id, id::text) FROM ( SELECT * FROM abbrev_abort_uuids UNIONALL SELECTNULL, NULL, NULL, NULL, NULL) s;
ROLLBACK;
---- -- test tuplesort mark/restore ---
CREATE TEMP TABLE test_mark_restore(col1 int, col2 int, col12 int); -- need a few duplicates for mark/restore to matter INSERTINTO test_mark_restore(col1, col2, col12) SELECT a.i, b.i, a.i * b.i FROM generate_series(1, 500) a(i), generate_series(1, 5) b(i);
BEGIN;
SET LOCAL enable_nestloop = off; SET LOCAL enable_hashjoin = off; SET LOCAL enable_material = off;
-- set query into variable once, to avoid repetition of the fairly long query SELECT $$ SELECT col12, count(distinct a.col1), count(distinct a.col2), count(distinct b.col1), count(distinct b.col2), count(*) FROM test_mark_restore a JOIN test_mark_restore b USING(col12) GROUPBY1 HAVING count(*) > 1 ORDERBY2DESC, 1DESC, 3DESC, 4DESC, 5DESC, 6DESC LIMIT10
$$ AS qry \gset
-- test mark/restore with in-memory sorts EXPLAIN (COSTS OFF) :qry;
:qry;
-- test mark/restore with on-disk sorts SET LOCAL work_mem = '100kB'; EXPLAIN (COSTS OFF) :qry;
:qry;
COMMIT;
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.