From 1a0dcde924ce020d8e3ff7242a8874bc3da70bfa Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Wed, 8 May 2024 20:32:20 +0300 Subject: [PATCH v1 2/2] Don't copy extended statistics during MERGE/SPLIT partition operations Currenlty MERGE/SPLIT partition operations create new partiions copying the extended statistics from the parent table. However, parent's table extended statistics already covers all its children. Also, "CREATE TABLE ... PARTITION OF" command doesn't copy extended statistics. This commit makes createPartitionTable() skip copying extended statistics from the parent. Reported-by: Justin Pryzby Discussion: https://postgr.es/m/ZiJW1g2nbQs9ekwK%40pryzbyj2023 --- doc/src/sgml/ref/alter_table.sgml | 8 ++++-- src/backend/commands/tablecmds.c | 8 +++--- src/test/regress/expected/partition_merge.out | 17 ++++++++++++ src/test/regress/expected/partition_split.out | 27 +++++++++++++++++++ src/test/regress/sql/partition_merge.sql | 10 +++++++ src/test/regress/sql/partition_split.sql | 12 +++++++++ 6 files changed, 77 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 0bf11f6cb6d..a11a407b7a6 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -1155,9 +1155,11 @@ WITH ( MODULUS numeric_literal, REM The new partitions will be created the same as tables created with the - SQL command CREATE TABLE partition_nameN (LIKE name INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY). + SQL command CREATE TABLE partition_nameN (LIKE name INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY EXCLUDING STATISTICS). The indexes and identity are created later, after moving the data into the new partitions. + The extended statistics aren't copied from the parent table, since + the parent's statistics cover all children and it's typically enough. New partitions will have the same table access method as the parent. If the parent table is persistent then new partitions are created persistent. If the parent table is temporary then new partitions @@ -1225,9 +1227,11 @@ WITH ( MODULUS numeric_literal, REM The new partition will be created the same as a table created with the - SQL command CREATE TABLE partition_name (LIKE name INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY). + SQL command CREATE TABLE partition_name (LIKE name INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY EXCLUDING STATISTICS). The indexes and identity are created later, after moving the data into the new partition. + The extended statistics aren't copied from the parent table, since + the parent's statistics cover all children and it's typically enough. The new partition will have the same table access method as the parent. If the parent table is persistent then the new partition is created persistent. If the parent table is temporary then the new partition diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 5bf5e69c5b8..dddf694b787 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -21245,7 +21245,7 @@ moveSplitTableRows(Relation rel, Relation splitRel, List *partlist, List *newPar * (newPartName) like table (modelRel) * * Emulates command: CREATE [TEMP] TABLE (LIKE - * INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY) + * INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY EXCLUDING STATISTICS) * * Also, this function sets the new partition access method same as parent * table access methods (similarly to CREATE TABLE ... PARTITION OF). It @@ -21289,9 +21289,11 @@ createPartitionTable(RangeVar *newPartName, Relation modelRel, /* * Indexes will be inherited on "attach new partitions" stage, after data - * moving. + * moving. We also don't copy the extended statistics since the parent's + * statistics cover all children and it's typically enough. */ - tlc->options = CREATE_TABLE_LIKE_ALL & ~(CREATE_TABLE_LIKE_INDEXES | CREATE_TABLE_LIKE_IDENTITY); + tlc->options = CREATE_TABLE_LIKE_ALL & + ~(CREATE_TABLE_LIKE_INDEXES | CREATE_TABLE_LIKE_IDENTITY | CREATE_TABLE_LIKE_STATISTICS); tlc->relationOid = InvalidOid; createStmt->tableElts = lappend(createStmt->tableElts, tlc); diff --git a/src/test/regress/expected/partition_merge.out b/src/test/regress/expected/partition_merge.out index 076264c88eb..36a60d7472c 100644 --- a/src/test/regress/expected/partition_merge.out +++ b/src/test/regress/expected/partition_merge.out @@ -910,6 +910,23 @@ RESET SESSION AUTHORIZATION; DROP TABLE t; DROP ROLE regress_partition_merge_alice; DROP ROLE regress_partition_merge_bob; +-- Check extended statistics aren't copied from the parent table to the new +-- partition. +CREATE TABLE t (i int, j int) PARTITION BY RANGE (i); +CREATE STATISTICS t_i_j (mcv) ON i, j FROM t; +CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); +CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); +ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; +\d+ tp_0_2 + Table "partitions_merge_schema.tp_0_2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + i | integer | | | | plain | | + j | integer | | | | plain | | +Partition of: t FOR VALUES FROM (0) TO (2) +Partition constraint: ((i IS NOT NULL) AND (i >= 0) AND (i < 2)) + +DROP TABLE t; RESET search_path; -- DROP SCHEMA partitions_merge_schema; diff --git a/src/test/regress/expected/partition_split.out b/src/test/regress/expected/partition_split.out index 74e19d250e9..461318db867 100644 --- a/src/test/regress/expected/partition_split.out +++ b/src/test/regress/expected/partition_split.out @@ -1543,6 +1543,33 @@ RESET SESSION AUTHORIZATION; DROP TABLE t; DROP ROLE regress_partition_merge_alice; DROP ROLE regress_partition_merge_bob; +-- Check extended statistics aren't copied from the parent table to new +-- partitions. +CREATE TABLE t (i int, j int) PARTITION BY RANGE (i); +CREATE STATISTICS t_i_j (mcv) ON i, j FROM t; +CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); +ALTER TABLE t SPLIT PARTITION tp_0_2 INTO + (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), + PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); +\d+ tp_0_1 + Table "partition_split_schema.tp_0_1" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + i | integer | | | | plain | | + j | integer | | | | plain | | +Partition of: t FOR VALUES FROM (0) TO (1) +Partition constraint: ((i IS NOT NULL) AND (i >= 0) AND (i < 1)) + +\d+ tp_1_2 + Table "partition_split_schema.tp_1_2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + i | integer | | | | plain | | + j | integer | | | | plain | | +Partition of: t FOR VALUES FROM (1) TO (2) +Partition constraint: ((i IS NOT NULL) AND (i >= 1) AND (i < 2)) + +DROP TABLE t; -- DROP SCHEMA partition_split_schema; DROP SCHEMA partition_split_schema2; diff --git a/src/test/regress/sql/partition_merge.sql b/src/test/regress/sql/partition_merge.sql index 9bfeb0d7ef3..203811b6e39 100644 --- a/src/test/regress/sql/partition_merge.sql +++ b/src/test/regress/sql/partition_merge.sql @@ -582,6 +582,16 @@ DROP TABLE t; DROP ROLE regress_partition_merge_alice; DROP ROLE regress_partition_merge_bob; +-- Check extended statistics aren't copied from the parent table to the new +-- partition. +CREATE TABLE t (i int, j int) PARTITION BY RANGE (i); +CREATE STATISTICS t_i_j (mcv) ON i, j FROM t; +CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1); +CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2); +ALTER TABLE t MERGE PARTITIONS (tp_0_1, tp_1_2) INTO tp_0_2; +\d+ tp_0_2 +DROP TABLE t; + RESET search_path; -- diff --git a/src/test/regress/sql/partition_split.sql b/src/test/regress/sql/partition_split.sql index bb52514b7ed..dc7424256e8 100644 --- a/src/test/regress/sql/partition_split.sql +++ b/src/test/regress/sql/partition_split.sql @@ -927,6 +927,18 @@ DROP TABLE t; DROP ROLE regress_partition_merge_alice; DROP ROLE regress_partition_merge_bob; +-- Check extended statistics aren't copied from the parent table to new +-- partitions. +CREATE TABLE t (i int, j int) PARTITION BY RANGE (i); +CREATE STATISTICS t_i_j (mcv) ON i, j FROM t; +CREATE TABLE tp_0_2 PARTITION OF t FOR VALUES FROM (0) TO (2); +ALTER TABLE t SPLIT PARTITION tp_0_2 INTO + (PARTITION tp_0_1 FOR VALUES FROM (0) TO (1), + PARTITION tp_1_2 FOR VALUES FROM (1) TO (2)); +\d+ tp_0_1 +\d+ tp_1_2 +DROP TABLE t; + -- DROP SCHEMA partition_split_schema; -- 2.39.3 (Apple Git-145)