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
要创建的统计信息对象的名称(可选地符合 schema 规范)。如果省略名称,PostgreSQL 将根据父表的名称和定义的列名和/或表达式选择一个合适的名称。
statistics_kind
此统计信息对象中要计算的多变量统计信息类型。当前支持的类型有 ndistinct
(启用 n distinct 统计信息),dependencies
(启用函数依赖性统计信息)和 mcv
(启用最常见值列表)。如果省略此子句,所有受支持的统计信息类型均包含在统计信息对象中。如果统计信息定义仅包含简单列引用,而不是复杂表达式,则会自动构建单变量表达式统计信息。有关详细信息,请参见 第 14.2.2 节 和 第 68.2 节。
column_name
已计算统计信息所涵盖的表列的名称。仅在构建多变量统计信息时才允许这样做。必须至少指定两个列名或表达式,且它们的顺序无关紧要。
expression
已计算统计信息所涵盖的表达式。这可用于在单个表达式上构建单变量统计信息,或用作构建多变量统计信息的多个列名和/或表达式的列表的一部分。在后一种情况下,将自动为列表中的每个表达式构建独立的单变量统计信息。
table_name
包含已针对其计算统计信息的列的表名称(可选地符合 schema 规范);请参见 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
条件是独立的,并将它们的 selectivity 相乘,以得出非常小的行计数估计。使用这样的统计数据,计划程序将识别到 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 列表向计划程序提供了关于表中通常出现的特定值的更详细信息,以及一个对表中未出现的组合值的 selectivity 的上限,从而允许它在两种情况下生成更好的估计。
创建表 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% 的 selectivity,表达式中的不同值的数量假定与列中的相同(即唯一)。这将导致对前两个查询中的行计数出现严重低估。此外,计划程序也没有关于表达式之间关系的信息,因此它假定这两个 WHERE
和 GROUP BY
条件是独立的,并将它们的 selectivity 相乘,以获得总体查询中组计数严重高估的值。由于没有针对表达式的准确统计数据,情况进一步恶化,迫使计划程序使用从列的 ndistinct 导出的表达式的默认 ndistinct 估计。使用这样的统计数据,计划程序将识别到这些条件是相关的,并得出更加准确的估计值。
SQL 标准中没有 CREATE STATISTICS
命令。