CREATE STATISTICS
— 定义扩展统计信息
CREATE STATISTICS [ [ IF NOT EXISTS ]statistics_name
] ON (expression
) FROMtable_name
CREATE STATISTICS [ [ IF NOT EXISTS ]statistics_name
] [ (statistics_kind
[, ... ] ) ] ON {column_name
| (expression
) }, {column_name
| (expression
) } [, ...] FROMtable_name
CREATE STATISTICS
命令将创建一个新的扩展统计信息对象,用于跟踪指定表、外部表或物化视图的数据。此统计信息对象将在当前数据库中创建,并由发出命令的用户拥有。
CREATE STATISTICS
命令有两种基本形式。第一种形式允许收集单个表达式的单变量统计信息,其好处类似于表达式索引,但没有索引维护的开销。此形式不允许指定统计信息种类,因为各种统计信息种类仅指多变量统计信息。该命令的第二种形式允许收集多个列和/或表达式的多变量统计信息,并可选择指定要包含的统计信息种类。此形式还将自动收集列表中包含的任何表达式的单变量统计信息。
如果给出了模式名(例如,CREATE STATISTICS myschema.mystat ...
),则统计信息对象将在指定的模式中创建。否则,它将在当前模式中创建。如果给出了统计信息对象的名称,则该名称在同一模式中的任何其他统计信息对象名称都必须不同。
IF NOT EXISTS
如果已存在同名统计信息对象,则不报错,而是发出通知。请注意,这里只考虑统计信息对象的名称,而不考虑其定义的详细信息。当指定 IF NOT EXISTS
时,统计信息名称是必需的。
statistics_name
要创建的统计信息对象的名称(可选模式限定)。如果省略名称,PostgreSQL 将根据父表名称以及定义的列名称和/或表达式选择一个合适的名称。
statistics_kind
在此统计信息对象中计算的多变量统计信息种类。当前支持的种类有:ndistinct
,它启用 n-distinct 统计信息;dependencies
,它启用函数依赖统计信息;以及 mcv
,它启用最常见值列表。如果省略此子句,则所有支持的统计信息种类都将包含在此统计信息对象中。如果统计信息定义包含复杂的表达式而不是简单的列引用,则会自动构建单变量表达式统计信息。有关更多信息,请参阅 第 14.2.2 节 和 第 69.2 节。
column_name
将被计算的统计信息覆盖的表列的名称。仅在构建多变量统计信息时允许。至少必须指定两个列名或表达式,它们的顺序不重要。
expression
将被计算的统计信息覆盖的表达式。这可以用于为单个表达式构建单变量统计信息,或作为构建多变量统计信息的多个列名和/或表达式列表的一部分。在后一种情况下,列表中的每个表达式都会自动构建单独的单变量统计信息。
table_name
用于计算统计信息的表(可选模式限定)的名称;请参阅 ANALYZE 以了解继承和分区的处理方式。
要创建读取它的表上的统计信息对象,您必须是该表的拥有者。但是,一旦创建,统计信息对象的所有权就独立于底层表。
表达式统计信息是按表达式计算的,类似于在表达式上创建索引,不同之处在于它们避免了索引维护的开销。表达式统计信息会为统计信息对象定义中的每个表达式自动构建。
当前规划器不使用扩展统计信息来估算表连接的选择性。此限制将来可能会在 PostgreSQL 的新版本中被移除。
创建表 t1
,该表有两个函数依赖的列,即,了解第一个列的值足以确定第二个列的值。然后,将在这些列上构建函数依赖统计信息。
CREATE TABLE t1 ( a int, b int ); INSERT INTO t1 SELECT i/100, i/500 FROM generate_series(1,1000000) s(i); ANALYZE t1; -- the number of matching rows will be drastically underestimated: EXPLAIN ANALYZE SELECT * FROM t1 WHERE (a = 1) AND (b = 0); CREATE STATISTICS s1 (dependencies) ON a, b FROM t1; ANALYZE t1; -- now the row count estimate is more accurate: EXPLAIN ANALYZE SELECT * FROM t1 WHERE (a = 1) AND (b = 0);
如果没有函数依赖统计信息,规划器会假设两个 WHERE
子句是独立的,并将它们的选择性相乘,从而得到一个低得离谱的行数估算。有了这样的统计信息,规划器就会识别出 WHERE
子句是冗余的,就不会低估行数。
创建表 t2
,该表有两个完全相关的列(包含相同的数据),并在这些列上建立 MCV 列表。
CREATE TABLE t2 ( a int, b int ); INSERT INTO t2 SELECT mod(i,100), mod(i,100) FROM generate_series(1,1000000) s(i); CREATE STATISTICS s2 (mcv) ON a, b FROM t2; ANALYZE t2; -- valid combination (found in MCV) EXPLAIN ANALYZE SELECT * FROM t2 WHERE (a = 1) AND (b = 1); -- invalid combination (not found in MCV) EXPLAIN ANALYZE SELECT * FROM t2 WHERE (a = 1) AND (b = 2);
MCV 列表为规划器提供了关于表中常见值的具体值的更详细信息,以及对未出现在表中的值组合的选择性的上限,从而使它在这两种情况下都能生成更好的估算。
创建表 t3
,该表有一个单独的时间戳列,并对该列上的表达式运行查询。如果没有扩展统计信息,规划器将不知道表达式的数据分布信息,并使用默认估算。规划器也不知道按月份截断的日期值完全由按天截断的日期值确定。然后,将在这两个表达式上构建表达式和 ndistinct 统计信息。
CREATE TABLE t3 ( a timestamp ); INSERT INTO t3 SELECT i FROM generate_series('2020-01-01'::timestamp, '2020-12-31'::timestamp, '1 minute'::interval) s(i); ANALYZE t3; -- the number of matching rows will be drastically underestimated: EXPLAIN ANALYZE SELECT * FROM t3 WHERE date_trunc('month', a) = '2020-01-01'::timestamp; EXPLAIN ANALYZE SELECT * FROM t3 WHERE date_trunc('day', a) BETWEEN '2020-01-01'::timestamp AND '2020-06-30'::timestamp; EXPLAIN ANALYZE SELECT date_trunc('month', a), date_trunc('day', a) FROM t3 GROUP BY 1, 2; -- build ndistinct statistics on the pair of expressions (per-expression -- statistics are built automatically) CREATE STATISTICS s3 (ndistinct) ON date_trunc('month', a), date_trunc('day', a) FROM t3; ANALYZE t3; -- now the row count estimates are more accurate: EXPLAIN ANALYZE SELECT * FROM t3 WHERE date_trunc('month', a) = '2020-01-01'::timestamp; EXPLAIN ANALYZE SELECT * FROM t3 WHERE date_trunc('day', a) BETWEEN '2020-01-01'::timestamp AND '2020-06-30'::timestamp; EXPLAIN ANALYZE SELECT date_trunc('month', a), date_trunc('day', a) FROM t3 GROUP BY 1, 2;
如果没有表达式和 ndistinct 统计信息,规划器将不知道表达式的唯一值数量,并且必须依赖默认估算。相等和范围条件被假定为 0.5% 的选择性,并且表达式的唯一值数量被假定与列的唯一值数量相同(即唯一)。这导致前两个查询的行数估算显著偏低。此外,规划器对表达式之间的关系没有信息,因此它假设两个 WHERE
和 GROUP BY
条件是独立的,并将它们选择性相乘,从而导致聚合查询的组计数严重高估。这由于表达式缺乏准确的统计信息而进一步加剧,迫使规划器使用从列的 ndistinct 估算派生的表达式的默认 ndistinct 估算。有了这样的统计信息,规划器就能识别出这些条件是相关的,并得到更准确的估算。
SQL 标准中没有 CREATE STATISTICS
命令。
如果您在文档中发现任何不正确、与您对特定功能的使用体验不符或需要进一步澄清的内容,请使用 此表格 报告文档问题。