-- Test functions used -- create n sequences. CREATE FUNCTION create_seq(n integer) RETURNS integer LANGUAGE plpgsql AS $$ BEGIN WHILE n > 0 LOOP EXECUTE 'CREATE SEQUENCE test' || CAST(n AS TEXT); n := n - 1; END LOOP; RETURN 0; END $$; -- call nextval() on n sequences. CREATE OR REPLACE FUNCTION nextval_seq(n integer) RETURNS integer LANGUAGE plpgsql AS $_$ BEGIN WHILE n > 0 LOOP EXECUTE $$SELECT nextval('test$$ || CAST(n AS TEXT) || $$')$$; n := n - 1; END LOOP; RETURN 0; END $_$; SELECT create_seq(30000); -- create 30000 sequences for testing SELECT nextval_seq(30000); -- call nextval() on each of these new sequences DROP TABLE IF EXISTS seq_test; -- create a table to test which uses a sequence which will be half way up the linked list. CREATE TABLE seq_test (id INT NOT NULL DEFAULT nextval('test15000'), value int not null); -- Test insert speed INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); /* Unpatched. postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 556.273 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 552.356 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 671.185 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 579.625 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 731.435 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 617.625 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 544.717 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 528.094 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 */ /* Patched postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 483.862 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 502.937 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 458.579 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 526.599 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 392.625 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 457.124 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 437.965 ms postgres=# INSERT INTO seq_test (value) SELECT value FROM generate_series(1,100000) s(value); INSERT 0 100000 Time: 598.410 ms */ -- Test DISCARD SEQUENCES; CREATE OR REPLACE FUNCTION currval_loop(n integer) RETURNS integer LANGUAGE plpgsql AS $_$ BEGIN WHILE n > 0 LOOP EXECUTE $$SELECT currval('test1');$$; n := n - 1; END LOOP; RETURN 0; END $_$; /* patched postgres=# select nextval('test1'); nextval --------- 63 (1 row) Time: 6.932 ms postgres=# select currval_loop(100000); -- in list mode with 1 sequence in the cache. currval_loop -------------- 0 (1 row) Time: 1856.452 ms postgres=# select nextval_seq(32); -- fill sequence cache to 1 less than the switchover point nextval_seq ------------- 0 (1 row) Time: 3.404 ms postgres=# select currval_loop(100000); -- test how the list cache performs with 32 sequences currval_loop -------------- 0 (1 row) Time: 1841.840 ms postgres=# select nextval_seq(33); -- one more to switch to the hash table NOTICE: moved sequences into hash table CONTEXT: SQL statement "SELECT nextval('test33')" PL/pgSQL function nextval_seq(integer) line 4 at EXECUTE statement nextval_seq ------------- 0 (1 row) Time: 21.401 ms postgres=# select currval_loop(100000); -- check how the loop on currval performs with the hashtable. currval_loop -------------- 0 (1 row) Time: 1861.558 ms postgres=# select nextval_seq(16000); -- fill the hashtable up to 16000 sequences. nextval_seq ------------- 0 (1 row) Time: 18646.860 ms postgres=# select currval_loop(100000); -- check how a loop over currval performs with 16000 in the hash table. currval_loop -------------- 0 (1 row) Time: 1963.711 ms */ /* unpatched postgres=# select nextval('test1'); -- put 1 sequence in the cache. nextval --------- 62 (1 row) Time: 1.458 ms postgres=# select currval_loop(100000); -- test performance with 1 sequence. currval_loop -------------- 0 (1 row) Time: 1844.110 ms postgres=# select nextval_seq(32); -- put 32 sequences in the list. nextval_seq ------------- 0 (1 row) Time: 57.925 ms postgres=# select currval_loop(100000); -- performance of 32 in sequence list. currval_loop -------------- 0 (1 row) Time: 1802.433 ms postgres=# select nextval_seq(16000); -- fill the list with 16000 sequences nextval_seq ------------- 0 (1 row) Time: 20680.676 ms postgres=# select currval_loop(100000); -- check performance of currval loop with 16000 sequences in the cache currval_loop -------------- 0 (1 row) Time: 10329.220 ms (patched version did this in 1963.711 ms) postgres=# */