2002-08-10 16:43:46 -04:00
|
|
|
--
|
|
|
|
|
-- CLUSTER
|
|
|
|
|
--
|
|
|
|
|
|
|
|
|
|
CREATE TABLE clstr_tst_s (rf_a SERIAL PRIMARY KEY,
|
|
|
|
|
b INT);
|
|
|
|
|
|
|
|
|
|
CREATE TABLE clstr_tst (a SERIAL PRIMARY KEY,
|
|
|
|
|
b INT,
|
|
|
|
|
c TEXT,
|
2002-08-11 17:17:35 -04:00
|
|
|
d TEXT,
|
2002-08-10 16:43:46 -04:00
|
|
|
CONSTRAINT clstr_tst_con FOREIGN KEY (b) REFERENCES clstr_tst_s);
|
|
|
|
|
|
|
|
|
|
CREATE INDEX clstr_tst_b ON clstr_tst (b);
|
|
|
|
|
CREATE INDEX clstr_tst_c ON clstr_tst (c);
|
|
|
|
|
CREATE INDEX clstr_tst_c_b ON clstr_tst (c,b);
|
|
|
|
|
CREATE INDEX clstr_tst_b_c ON clstr_tst (b,c);
|
|
|
|
|
|
|
|
|
|
INSERT INTO clstr_tst_s (b) VALUES (0);
|
|
|
|
|
INSERT INTO clstr_tst_s (b) SELECT b FROM clstr_tst_s;
|
|
|
|
|
INSERT INTO clstr_tst_s (b) SELECT b FROM clstr_tst_s;
|
|
|
|
|
INSERT INTO clstr_tst_s (b) SELECT b FROM clstr_tst_s;
|
|
|
|
|
INSERT INTO clstr_tst_s (b) SELECT b FROM clstr_tst_s;
|
|
|
|
|
INSERT INTO clstr_tst_s (b) SELECT b FROM clstr_tst_s;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE clstr_tst_inh () INHERITS (clstr_tst);
|
|
|
|
|
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (11, 'once');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (10, 'diez');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (31, 'treinta y uno');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (22, 'veintidos');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (3, 'tres');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (20, 'veinte');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (23, 'veintitres');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (21, 'veintiuno');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (4, 'cuatro');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (14, 'catorce');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (2, 'dos');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (18, 'dieciocho');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (27, 'veintisiete');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (25, 'veinticinco');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (13, 'trece');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (28, 'veintiocho');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (32, 'treinta y dos');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (5, 'cinco');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (29, 'veintinueve');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (1, 'uno');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (24, 'veinticuatro');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (30, 'treinta');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (12, 'doce');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (17, 'diecisiete');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (9, 'nueve');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (19, 'diecinueve');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (26, 'veintiseis');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (15, 'quince');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (7, 'siete');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (16, 'dieciseis');
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (8, 'ocho');
|
2002-08-11 17:17:35 -04:00
|
|
|
-- This entry is needed to test that TOASTED values are copied correctly.
|
|
|
|
|
INSERT INTO clstr_tst (b, c, d) VALUES (6, 'seis', repeat('xyzzy', 100000));
|
2002-08-10 16:43:46 -04:00
|
|
|
|
|
|
|
|
CLUSTER clstr_tst_c ON clstr_tst;
|
|
|
|
|
|
2002-08-11 17:17:35 -04:00
|
|
|
SELECT a,b,c,substring(d for 30), length(d) from clstr_tst;
|
|
|
|
|
SELECT a,b,c,substring(d for 30), length(d) from clstr_tst ORDER BY a;
|
|
|
|
|
SELECT a,b,c,substring(d for 30), length(d) from clstr_tst ORDER BY b;
|
|
|
|
|
SELECT a,b,c,substring(d for 30), length(d) from clstr_tst ORDER BY c;
|
2002-08-10 16:43:46 -04:00
|
|
|
|
2002-08-10 22:06:32 -04:00
|
|
|
-- Verify that inheritance link still works
|
|
|
|
|
INSERT INTO clstr_tst_inh VALUES (0, 100, 'in child table');
|
2002-08-11 17:17:35 -04:00
|
|
|
SELECT a,b,c,substring(d for 30), length(d) from clstr_tst;
|
2002-08-10 22:06:32 -04:00
|
|
|
|
|
|
|
|
-- Verify that foreign key link still works
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail');
|
|
|
|
|
|
2007-09-02 21:28:40 -04:00
|
|
|
SELECT conname FROM pg_constraint WHERE conrelid = 'clstr_tst'::regclass
|
|
|
|
|
ORDER BY 1;
|
2002-08-10 16:43:46 -04:00
|
|
|
|
2002-08-11 17:17:35 -04:00
|
|
|
SELECT relname, relkind,
|
|
|
|
|
EXISTS(SELECT 1 FROM pg_class WHERE oid = c.reltoastrelid) AS hastoast
|
|
|
|
|
FROM pg_class c WHERE relname LIKE 'clstr_tst%' ORDER BY relname;
|
2002-08-26 23:38:28 -04:00
|
|
|
|
|
|
|
|
-- Verify that indisclustered is correctly set
|
|
|
|
|
SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2
|
|
|
|
|
WHERE pg_class.oid=indexrelid
|
|
|
|
|
AND indrelid=pg_class_2.oid
|
|
|
|
|
AND pg_class_2.relname = 'clstr_tst'
|
|
|
|
|
AND indisclustered;
|
2002-11-14 22:09:39 -05:00
|
|
|
|
2003-03-20 13:52:48 -05:00
|
|
|
-- Try changing indisclustered
|
|
|
|
|
ALTER TABLE clstr_tst CLUSTER ON clstr_tst_b_c;
|
|
|
|
|
SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2
|
|
|
|
|
WHERE pg_class.oid=indexrelid
|
|
|
|
|
AND indrelid=pg_class_2.oid
|
|
|
|
|
AND pg_class_2.relname = 'clstr_tst'
|
|
|
|
|
AND indisclustered;
|
|
|
|
|
|
2004-06-02 17:01:10 -04:00
|
|
|
-- Try turning off all clustering
|
|
|
|
|
ALTER TABLE clstr_tst SET WITHOUT CLUSTER;
|
|
|
|
|
SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2
|
|
|
|
|
WHERE pg_class.oid=indexrelid
|
|
|
|
|
AND indrelid=pg_class_2.oid
|
|
|
|
|
AND pg_class_2.relname = 'clstr_tst'
|
|
|
|
|
AND indisclustered;
|
|
|
|
|
|
2022-04-02 13:08:34 -04:00
|
|
|
-- Verify that toast tables are clusterable
|
|
|
|
|
CLUSTER pg_toast.pg_toast_826 USING pg_toast_826_index;
|
|
|
|
|
|
2002-11-14 22:09:39 -05:00
|
|
|
-- Verify that clustering all tables does in fact cluster the right ones
|
2016-07-17 18:42:31 -04:00
|
|
|
CREATE USER regress_clstr_user;
|
2002-11-14 22:09:39 -05:00
|
|
|
CREATE TABLE clstr_1 (a INT PRIMARY KEY);
|
|
|
|
|
CREATE TABLE clstr_2 (a INT PRIMARY KEY);
|
|
|
|
|
CREATE TABLE clstr_3 (a INT PRIMARY KEY);
|
2016-07-17 18:42:31 -04:00
|
|
|
ALTER TABLE clstr_1 OWNER TO regress_clstr_user;
|
|
|
|
|
ALTER TABLE clstr_3 OWNER TO regress_clstr_user;
|
|
|
|
|
GRANT SELECT ON clstr_2 TO regress_clstr_user;
|
2002-11-14 22:09:39 -05:00
|
|
|
INSERT INTO clstr_1 VALUES (2);
|
|
|
|
|
INSERT INTO clstr_1 VALUES (1);
|
|
|
|
|
INSERT INTO clstr_2 VALUES (2);
|
|
|
|
|
INSERT INTO clstr_2 VALUES (1);
|
|
|
|
|
INSERT INTO clstr_3 VALUES (2);
|
|
|
|
|
INSERT INTO clstr_3 VALUES (1);
|
|
|
|
|
|
|
|
|
|
-- "CLUSTER <tablename>" on a table that hasn't been clustered
|
|
|
|
|
CLUSTER clstr_2;
|
|
|
|
|
|
|
|
|
|
CLUSTER clstr_1_pkey ON clstr_1;
|
2007-04-07 20:26:34 -04:00
|
|
|
CLUSTER clstr_2 USING clstr_2_pkey;
|
2002-11-14 22:09:39 -05:00
|
|
|
SELECT * FROM clstr_1 UNION ALL
|
|
|
|
|
SELECT * FROM clstr_2 UNION ALL
|
|
|
|
|
SELECT * FROM clstr_3;
|
|
|
|
|
|
|
|
|
|
-- revert to the original state
|
|
|
|
|
DELETE FROM clstr_1;
|
|
|
|
|
DELETE FROM clstr_2;
|
|
|
|
|
DELETE FROM clstr_3;
|
|
|
|
|
INSERT INTO clstr_1 VALUES (2);
|
|
|
|
|
INSERT INTO clstr_1 VALUES (1);
|
|
|
|
|
INSERT INTO clstr_2 VALUES (2);
|
|
|
|
|
INSERT INTO clstr_2 VALUES (1);
|
|
|
|
|
INSERT INTO clstr_3 VALUES (2);
|
|
|
|
|
INSERT INTO clstr_3 VALUES (1);
|
|
|
|
|
|
|
|
|
|
-- this user can only cluster clstr_1 and clstr_3, but the latter
|
|
|
|
|
-- has not been clustered
|
2016-07-17 18:42:31 -04:00
|
|
|
SET SESSION AUTHORIZATION regress_clstr_user;
|
2024-03-13 15:49:26 -04:00
|
|
|
SET client_min_messages = ERROR; -- order of "skipping" warnings may vary
|
2002-11-19 12:39:00 -05:00
|
|
|
CLUSTER;
|
2024-03-13 15:49:26 -04:00
|
|
|
RESET client_min_messages;
|
2002-11-14 22:09:39 -05:00
|
|
|
SELECT * FROM clstr_1 UNION ALL
|
|
|
|
|
SELECT * FROM clstr_2 UNION ALL
|
|
|
|
|
SELECT * FROM clstr_3;
|
|
|
|
|
|
|
|
|
|
-- cluster a single table using the indisclustered bit previously set
|
|
|
|
|
DELETE FROM clstr_1;
|
|
|
|
|
INSERT INTO clstr_1 VALUES (2);
|
|
|
|
|
INSERT INTO clstr_1 VALUES (1);
|
|
|
|
|
CLUSTER clstr_1;
|
|
|
|
|
SELECT * FROM clstr_1;
|
|
|
|
|
|
2007-04-07 21:26:33 -04:00
|
|
|
-- Test MVCC-safety of cluster. There isn't much we can do to verify the
|
|
|
|
|
-- results with a single backend...
|
|
|
|
|
|
|
|
|
|
CREATE TABLE clustertest (key int PRIMARY KEY);
|
|
|
|
|
|
|
|
|
|
INSERT INTO clustertest VALUES (10);
|
|
|
|
|
INSERT INTO clustertest VALUES (20);
|
|
|
|
|
INSERT INTO clustertest VALUES (30);
|
|
|
|
|
INSERT INTO clustertest VALUES (40);
|
|
|
|
|
INSERT INTO clustertest VALUES (50);
|
|
|
|
|
|
|
|
|
|
-- Use a transaction so that updates are not committed when CLUSTER sees 'em
|
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
|
|
-- Test update where the old row version is found first in the scan
|
|
|
|
|
UPDATE clustertest SET key = 100 WHERE key = 10;
|
|
|
|
|
|
|
|
|
|
-- Test update where the new row version is found first in the scan
|
|
|
|
|
UPDATE clustertest SET key = 35 WHERE key = 40;
|
|
|
|
|
|
2010-11-23 15:27:50 -05:00
|
|
|
-- Test longer update chain
|
2007-04-07 21:26:33 -04:00
|
|
|
UPDATE clustertest SET key = 60 WHERE key = 50;
|
|
|
|
|
UPDATE clustertest SET key = 70 WHERE key = 60;
|
|
|
|
|
UPDATE clustertest SET key = 80 WHERE key = 70;
|
|
|
|
|
|
|
|
|
|
SELECT * FROM clustertest;
|
|
|
|
|
CLUSTER clustertest_pkey ON clustertest;
|
|
|
|
|
SELECT * FROM clustertest;
|
|
|
|
|
|
|
|
|
|
COMMIT;
|
|
|
|
|
|
|
|
|
|
SELECT * FROM clustertest;
|
|
|
|
|
|
2010-02-02 14:12:29 -05:00
|
|
|
-- check that temp tables can be clustered
|
|
|
|
|
create temp table clstr_temp (col1 int primary key, col2 text);
|
|
|
|
|
insert into clstr_temp values (2, 'two'), (1, 'one');
|
|
|
|
|
cluster clstr_temp using clstr_temp_pkey;
|
|
|
|
|
select * from clstr_temp;
|
2010-02-02 22:21:25 -05:00
|
|
|
drop table clstr_temp;
|
2010-02-02 14:12:29 -05:00
|
|
|
|
2016-07-13 15:23:56 -04:00
|
|
|
RESET SESSION AUTHORIZATION;
|
|
|
|
|
|
2021-03-23 11:24:16 -04:00
|
|
|
-- check clustering an empty table
|
|
|
|
|
DROP TABLE clustertest;
|
|
|
|
|
CREATE TABLE clustertest (f1 int PRIMARY KEY);
|
|
|
|
|
CLUSTER clustertest USING clustertest_pkey;
|
|
|
|
|
CLUSTER clustertest;
|
|
|
|
|
|
2022-04-02 13:08:34 -04:00
|
|
|
-- Check that partitioned tables can be clustered
|
2018-01-25 14:11:51 -05:00
|
|
|
CREATE TABLE clstrpart (a int) PARTITION BY RANGE (a);
|
2022-04-02 13:08:34 -04:00
|
|
|
CREATE TABLE clstrpart1 PARTITION OF clstrpart FOR VALUES FROM (1) TO (10) PARTITION BY RANGE (a);
|
|
|
|
|
CREATE TABLE clstrpart11 PARTITION OF clstrpart1 FOR VALUES FROM (1) TO (5);
|
|
|
|
|
CREATE TABLE clstrpart12 PARTITION OF clstrpart1 FOR VALUES FROM (5) TO (10) PARTITION BY RANGE (a);
|
|
|
|
|
CREATE TABLE clstrpart2 PARTITION OF clstrpart FOR VALUES FROM (10) TO (20);
|
|
|
|
|
CREATE TABLE clstrpart3 PARTITION OF clstrpart DEFAULT PARTITION BY RANGE (a);
|
|
|
|
|
CREATE TABLE clstrpart33 PARTITION OF clstrpart3 DEFAULT;
|
|
|
|
|
CREATE INDEX clstrpart_only_idx ON ONLY clstrpart (a);
|
|
|
|
|
CLUSTER clstrpart USING clstrpart_only_idx; -- fails
|
|
|
|
|
DROP INDEX clstrpart_only_idx;
|
2018-01-25 14:11:51 -05:00
|
|
|
CREATE INDEX clstrpart_idx ON clstrpart (a);
|
2022-04-02 13:08:34 -04:00
|
|
|
-- Check that clustering sets new relfilenodes:
|
|
|
|
|
CREATE TEMP TABLE old_cluster_info AS SELECT relname, level, relfilenode, relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class c ON c.oid=tree.relid ;
|
2018-01-25 14:11:51 -05:00
|
|
|
CLUSTER clstrpart USING clstrpart_idx;
|
2022-04-02 13:08:34 -04:00
|
|
|
CREATE TEMP TABLE new_cluster_info AS SELECT relname, level, relfilenode, relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class c ON c.oid=tree.relid ;
|
|
|
|
|
SELECT relname, old.level, old.relkind, old.relfilenode = new.relfilenode FROM old_cluster_info AS old JOIN new_cluster_info AS new USING (relname) ORDER BY relname COLLATE "C";
|
|
|
|
|
-- Partitioned indexes aren't and can't be marked un/clustered:
|
|
|
|
|
\d clstrpart
|
|
|
|
|
CLUSTER clstrpart;
|
|
|
|
|
ALTER TABLE clstrpart SET WITHOUT CLUSTER;
|
|
|
|
|
ALTER TABLE clstrpart CLUSTER ON clstrpart_idx;
|
2026-03-10 14:56:39 -04:00
|
|
|
-- and they cannot get an index-ordered REPACK without an explicit index name
|
|
|
|
|
REPACK clstrpart USING INDEX;
|
|
|
|
|
|
|
|
|
|
-- Check that REPACK sets new relfilenodes: it should process exactly the same
|
|
|
|
|
-- tables as CLUSTER did.
|
|
|
|
|
DROP TABLE old_cluster_info;
|
|
|
|
|
DROP TABLE new_cluster_info;
|
|
|
|
|
CREATE TEMP TABLE old_cluster_info AS SELECT relname, level, relfilenode, relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class c ON c.oid=tree.relid ;
|
|
|
|
|
REPACK clstrpart USING INDEX clstrpart_idx;
|
|
|
|
|
CREATE TEMP TABLE new_cluster_info AS SELECT relname, level, relfilenode, relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class c ON c.oid=tree.relid ;
|
|
|
|
|
SELECT relname, old.level, old.relkind, old.relfilenode = new.relfilenode FROM old_cluster_info AS old JOIN new_cluster_info AS new USING (relname) ORDER BY relname COLLATE "C";
|
|
|
|
|
|
|
|
|
|
-- And finally the same for REPACK w/o index.
|
|
|
|
|
DROP TABLE old_cluster_info;
|
|
|
|
|
DROP TABLE new_cluster_info;
|
|
|
|
|
CREATE TEMP TABLE old_cluster_info AS SELECT relname, level, relfilenode, relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class c ON c.oid=tree.relid ;
|
|
|
|
|
REPACK clstrpart;
|
|
|
|
|
CREATE TEMP TABLE new_cluster_info AS SELECT relname, level, relfilenode, relkind FROM pg_partition_tree('clstrpart'::regclass) AS tree JOIN pg_class c ON c.oid=tree.relid ;
|
|
|
|
|
SELECT relname, old.level, old.relkind, old.relfilenode = new.relfilenode FROM old_cluster_info AS old JOIN new_cluster_info AS new USING (relname) ORDER BY relname COLLATE "C";
|
|
|
|
|
|
2026-04-06 15:55:08 -04:00
|
|
|
-- CONCURRENTLY doesn't like partitioned tables
|
|
|
|
|
REPACK (CONCURRENTLY) clstrpart;
|
|
|
|
|
|
2018-01-25 14:11:51 -05:00
|
|
|
DROP TABLE clstrpart;
|
|
|
|
|
|
2022-04-14 16:11:06 -04:00
|
|
|
-- Ownership of partitions is checked
|
|
|
|
|
CREATE TABLE ptnowner(i int unique) PARTITION BY LIST (i);
|
|
|
|
|
CREATE INDEX ptnowner_i_idx ON ptnowner(i);
|
|
|
|
|
CREATE TABLE ptnowner1 PARTITION OF ptnowner FOR VALUES IN (1);
|
|
|
|
|
CREATE ROLE regress_ptnowner;
|
|
|
|
|
CREATE TABLE ptnowner2 PARTITION OF ptnowner FOR VALUES IN (2);
|
|
|
|
|
ALTER TABLE ptnowner1 OWNER TO regress_ptnowner;
|
2024-03-13 15:49:26 -04:00
|
|
|
SET SESSION AUTHORIZATION regress_ptnowner;
|
|
|
|
|
CLUSTER ptnowner USING ptnowner_i_idx;
|
|
|
|
|
RESET SESSION AUTHORIZATION;
|
2022-04-14 16:11:06 -04:00
|
|
|
ALTER TABLE ptnowner OWNER TO regress_ptnowner;
|
|
|
|
|
CREATE TEMP TABLE ptnowner_oldnodes AS
|
|
|
|
|
SELECT oid, relname, relfilenode FROM pg_partition_tree('ptnowner') AS tree
|
|
|
|
|
JOIN pg_class AS c ON c.oid=tree.relid;
|
|
|
|
|
SET SESSION AUTHORIZATION regress_ptnowner;
|
|
|
|
|
CLUSTER ptnowner USING ptnowner_i_idx;
|
|
|
|
|
RESET SESSION AUTHORIZATION;
|
|
|
|
|
SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a
|
|
|
|
|
JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C";
|
|
|
|
|
DROP TABLE ptnowner;
|
|
|
|
|
DROP ROLE regress_ptnowner;
|
|
|
|
|
|
2016-07-13 15:23:56 -04:00
|
|
|
-- Test CLUSTER with external tuplesorting
|
|
|
|
|
|
|
|
|
|
create table clstr_4 as select * from tenk1;
|
|
|
|
|
create index cluster_sort on clstr_4 (hundred, thousand, tenthous);
|
|
|
|
|
-- ensure we don't use the index in CLUSTER nor the checking SELECTs
|
|
|
|
|
set enable_indexscan = off;
|
|
|
|
|
|
2017-09-29 10:20:44 -04:00
|
|
|
-- Use external sort:
|
2016-07-13 15:23:56 -04:00
|
|
|
set maintenance_work_mem = '1MB';
|
|
|
|
|
cluster clstr_4 using cluster_sort;
|
|
|
|
|
select * from
|
|
|
|
|
(select hundred, lag(hundred) over () as lhundred,
|
|
|
|
|
thousand, lag(thousand) over () as lthousand,
|
|
|
|
|
tenthous, lag(tenthous) over () as ltenthous from clstr_4) ss
|
|
|
|
|
where row(hundred, thousand, tenthous) <= row(lhundred, lthousand, ltenthous);
|
|
|
|
|
|
|
|
|
|
reset enable_indexscan;
|
|
|
|
|
reset maintenance_work_mem;
|
|
|
|
|
|
2019-10-15 13:40:13 -04:00
|
|
|
-- test CLUSTER on expression index
|
|
|
|
|
CREATE TABLE clstr_expression(id serial primary key, a int, b text COLLATE "C");
|
|
|
|
|
INSERT INTO clstr_expression(a, b) SELECT g.i % 42, 'prefix'||g.i FROM generate_series(1, 133) g(i);
|
|
|
|
|
CREATE INDEX clstr_expression_minus_a ON clstr_expression ((-a), b);
|
|
|
|
|
CREATE INDEX clstr_expression_upper_b ON clstr_expression ((upper(b)));
|
|
|
|
|
|
|
|
|
|
-- verify indexes work before cluster
|
|
|
|
|
BEGIN;
|
|
|
|
|
SET LOCAL enable_seqscan = false;
|
|
|
|
|
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
|
|
|
|
|
SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
|
|
|
|
|
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
|
|
|
|
|
SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
|
|
|
|
|
COMMIT;
|
|
|
|
|
|
|
|
|
|
-- and after clustering on clstr_expression_minus_a
|
|
|
|
|
CLUSTER clstr_expression USING clstr_expression_minus_a;
|
2022-04-20 20:17:43 -04:00
|
|
|
WITH rows AS
|
|
|
|
|
(SELECT ctid, lag(a) OVER (ORDER BY ctid) AS la, a FROM clstr_expression)
|
|
|
|
|
SELECT * FROM rows WHERE la < a;
|
2019-10-15 13:40:13 -04:00
|
|
|
BEGIN;
|
|
|
|
|
SET LOCAL enable_seqscan = false;
|
|
|
|
|
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
|
|
|
|
|
SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
|
|
|
|
|
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
|
|
|
|
|
SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
|
|
|
|
|
COMMIT;
|
|
|
|
|
|
|
|
|
|
-- and after clustering on clstr_expression_upper_b
|
|
|
|
|
CLUSTER clstr_expression USING clstr_expression_upper_b;
|
2022-04-20 20:17:43 -04:00
|
|
|
WITH rows AS
|
|
|
|
|
(SELECT ctid, lag(b) OVER (ORDER BY ctid) AS lb, b FROM clstr_expression)
|
|
|
|
|
SELECT * FROM rows WHERE upper(lb) > upper(b);
|
2019-10-15 13:40:13 -04:00
|
|
|
BEGIN;
|
|
|
|
|
SET LOCAL enable_seqscan = false;
|
|
|
|
|
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
|
|
|
|
|
SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
|
|
|
|
|
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
|
|
|
|
|
SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
|
|
|
|
|
COMMIT;
|
|
|
|
|
|
2026-03-10 14:56:39 -04:00
|
|
|
----------------------------------------------------------------------
|
|
|
|
|
--
|
|
|
|
|
-- REPACK
|
|
|
|
|
--
|
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
-- REPACK handles individual tables identically to CLUSTER, but it's worth
|
|
|
|
|
-- checking if it handles table hierarchies identically as well.
|
|
|
|
|
REPACK clstr_tst USING INDEX clstr_tst_c;
|
|
|
|
|
|
|
|
|
|
-- Verify that inheritance link still works
|
|
|
|
|
INSERT INTO clstr_tst_inh VALUES (0, 100, 'in child table 2');
|
|
|
|
|
SELECT a,b,c,substring(d for 30), length(d) from clstr_tst;
|
|
|
|
|
|
|
|
|
|
-- Verify that foreign key link still works
|
|
|
|
|
INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail');
|
|
|
|
|
|
|
|
|
|
SELECT conname FROM pg_constraint WHERE conrelid = 'clstr_tst'::regclass
|
|
|
|
|
ORDER BY 1;
|
|
|
|
|
|
|
|
|
|
-- Verify partial analyze works
|
|
|
|
|
REPACK (ANALYZE) clstr_tst (a);
|
|
|
|
|
REPACK (ANALYZE) clstr_tst;
|
|
|
|
|
REPACK (VERBOSE) clstr_tst (a);
|
|
|
|
|
|
|
|
|
|
-- REPACK w/o argument performs no ordering, so we can only check which tables
|
|
|
|
|
-- have the relfilenode changed.
|
|
|
|
|
RESET SESSION AUTHORIZATION;
|
|
|
|
|
CREATE TEMP TABLE relnodes_old AS
|
|
|
|
|
(SELECT relname, relfilenode
|
|
|
|
|
FROM pg_class
|
|
|
|
|
WHERE relname IN ('clstr_1', 'clstr_2', 'clstr_3'));
|
|
|
|
|
|
|
|
|
|
SET SESSION AUTHORIZATION regress_clstr_user;
|
|
|
|
|
SET client_min_messages = ERROR; -- order of "skipping" warnings may vary
|
|
|
|
|
REPACK;
|
|
|
|
|
RESET client_min_messages;
|
|
|
|
|
|
|
|
|
|
RESET SESSION AUTHORIZATION;
|
|
|
|
|
CREATE TEMP TABLE relnodes_new AS
|
|
|
|
|
(SELECT relname, relfilenode
|
|
|
|
|
FROM pg_class
|
|
|
|
|
WHERE relname IN ('clstr_1', 'clstr_2', 'clstr_3'));
|
|
|
|
|
|
|
|
|
|
-- Do the actual comparison. Unlike CLUSTER, clstr_3 should have been
|
|
|
|
|
-- processed because there is nothing like clustering index here.
|
|
|
|
|
SELECT o.relname FROM relnodes_old o
|
|
|
|
|
JOIN relnodes_new n ON o.relname = n.relname
|
|
|
|
|
WHERE o.relfilenode <> n.relfilenode
|
|
|
|
|
ORDER BY o.relname;
|
|
|
|
|
|
2026-04-06 15:55:08 -04:00
|
|
|
-- concurrently
|
|
|
|
|
REPACK (CONCURRENTLY) pg_class;
|
|
|
|
|
|
2002-11-14 22:09:39 -05:00
|
|
|
-- clean up
|
2007-04-07 21:26:33 -04:00
|
|
|
DROP TABLE clustertest;
|
2002-11-14 22:09:39 -05:00
|
|
|
DROP TABLE clstr_1;
|
2005-07-07 16:40:02 -04:00
|
|
|
DROP TABLE clstr_2;
|
2002-11-14 22:09:39 -05:00
|
|
|
DROP TABLE clstr_3;
|
2016-07-13 15:23:56 -04:00
|
|
|
DROP TABLE clstr_4;
|
2019-10-15 13:40:13 -04:00
|
|
|
DROP TABLE clstr_expression;
|
|
|
|
|
|
2016-07-17 18:42:31 -04:00
|
|
|
DROP USER regress_clstr_user;
|