Don't build extended statistics on inheritance trees
authorTomas Vondra
Tue, 30 Jul 2019 17:17:12 +0000 (19:17 +0200)
committerTomas Vondra
Tue, 30 Jul 2019 17:48:39 +0000 (19:48 +0200)
When performing ANALYZE on inheritance trees, we collect two samples for
each relation - one for the relation alone, and one for the inheritance
subtree (relation and its child relations). And then we build statistics
on each sample, so for each relation we get two sets of statistics.

For regular (per-column) statistics this works fine, because the catalog
includes a flag differentiating statistics built from those two samples.
But we don't have such flag in the extended statistics catalogs, and we
ended up updating the same row twice, triggering this error:

  ERROR:  tuple already updated by self

The simplest solution is to disable extended statistics on inheritance
trees, which is what this commit is doing. In the future we may need to
do something similar to per-column statistics, but that requires adding a
flag to the catalog - and that's not backpatchable. Moreover, the current
selectivity estimation code only works with individual relations, so
building statistics on inheritance trees would be pointless anyway.

Author: Tomas Vondra
Backpatch-to: 10-
Discussion: https://postgr.es/m/20190618231233[email protected]
Reported-by: Justin Pryzby
src/backend/commands/analyze.c
src/test/regress/expected/stats_ext.out
src/test/regress/sql/stats_ext.sql

index 90b2bb1fea498a9ff88e61273e872398c8044895..37b77e28cb9abdf5fccdaf2ef96a1d494f7ede39 100644 (file)
@@ -589,9 +589,15 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params,
                            thisdata->attr_cnt, thisdata->vacattrstats);
        }
 
-       /* Build extended statistics (if there are any). */
-       BuildRelationExtStatistics(onerel, totalrows, numrows, rows, attr_cnt,
-                                  vacattrstats);
+       /*
+        * Build extended statistics (if there are any).
+        *
+        * For now we only build extended statistics on individual relations,
+        * not for relations representing inheritance trees.
+        */
+       if (!inh)
+           BuildRelationExtStatistics(onerel, totalrows, numrows, rows,
+                                      attr_cnt, vacattrstats);
    }
 
    /*
index 054a381dad3ee63a191720009807443a46f60cce..eebf250998e1959c03b2d21e17911ced0753d793 100644 (file)
@@ -86,6 +86,14 @@ ANALYZE ab1 (a);
 WARNING:  statistics object "public.ab1_a_b_stats" could not be computed for relation "public.ab1"
 ANALYZE ab1;
 DROP TABLE ab1;
+-- Ensure we can build statistics for tables with inheritance.
+CREATE TABLE ab1 (a INTEGER, b INTEGER);
+CREATE TABLE ab1c () INHERITS (ab1);
+INSERT INTO ab1 VALUES (1,1);
+CREATE STATISTICS ab1_a_b_stats ON a, b FROM ab1;
+ANALYZE ab1;
+DROP TABLE ab1 CASCADE;
+NOTICE:  drop cascades to table ab1c
 -- Verify supported object types for extended statistics
 CREATE schema tststats;
 CREATE TABLE tststats.t (a int, b int, c text);
index 46acaadb3932a7a891b480c449214ac442a1bad8..43ff77c5344e0f2b07bd5c5585da67e566d1c51f 100644 (file)
@@ -55,6 +55,14 @@ ANALYZE ab1 (a);
 ANALYZE ab1;
 DROP TABLE ab1;
 
+-- Ensure we can build statistics for tables with inheritance.
+CREATE TABLE ab1 (a INTEGER, b INTEGER);
+CREATE TABLE ab1c () INHERITS (ab1);
+INSERT INTO ab1 VALUES (1,1);
+CREATE STATISTICS ab1_a_b_stats ON a, b FROM ab1;
+ANALYZE ab1;
+DROP TABLE ab1 CASCADE;
+
 -- Verify supported object types for extended statistics
 CREATE schema tststats;