# 创建统计
CREATE STATISTICS — 定义扩展统计
# 概要
CREATE STATISTICS [ IF NOT EXISTS ] statistics_name
ON ( expression )
FROM table_name
CREATE STATISTICS [ IF NOT EXISTS ] statistics_name
[ ( statistics_kind [, ... ] ) ]
ON { column_name | ( expression ) }, { column_name | ( expression ) } [, ...]
FROM table_name
# 描述
创建统计
将创建一个新的扩展统计对象跟踪有关指定表、外部表或物化视图的数据。统计对象将在当前数据库中创建,并由发出命令的用户拥有。
这创建统计
命令有两种基本形式。第一种形式允许收集单个表达式的单变量统计信息,提供类似于表达式索引的好处,而无需索引维护的开销。这种形式不允许指定统计类型,因为各种统计类型仅指多变量统计。该命令的第二种形式允许收集关于多个列和/或表达式的多元统计信息,可选择指定要包括的统计信息类型。此表单还将自动收集列表中包含的任何表达式的单变量统计信息。
如果给出了模式名称(例如,创建统计信息 myschema.mystat ...
) 然后在指定的模式中创建统计对象。否则,它会在当前模式中创建。统计对象的名称必须与同一模式中的任何其他统计对象的名称不同。
# 参数
如果不存在
如果同名的统计对象已经存在,不要抛出错误。在这种情况下发出通知。请注意,这里只考虑统计对象的名称,而不考虑其定义的详细信息。
统计名称
要创建的统计对象的名称(可选的模式限定)。
统计种类
要在此统计对象中计算的多元统计类型。目前支持的种类是不明显
,它启用了 n 个不同的统计量,依赖关系
,它启用函数依赖统计,以及mcv
这启用了最常见的值列表。如果省略此子句,则所有支持的统计类型都包含在统计对象中。如果统计定义包括任何复杂的表达式,而不仅仅是简单的列引用,则会自动构建单变量表达式统计。有关详细信息,请参阅第 14.2.2 节和第 72.2 节.
列名
要被计算的统计信息覆盖的表列的名称。仅在构建多元统计数据时才允许这样做。必须至少指定两个列名或表达式,并且它们的顺序不重要。
表达
计算统计信息涵盖的表达式。这可用于在单个表达式上构建单变量统计信息,或作为多列名称和/或表达式列表的一部分来构建多变量统计信息。在后一种情况下,将为列表中的每个表达式自动构建单独的单变量统计信息。
表名
包含计算统计信息的列的表的名称(可选模式限定)。
# 笔记
您必须是表的所有者才能创建读取它的统计信息对象。但是,一旦创建,统计对象的所有权就独立于基础表。
表达式统计信息是针对每个表达式的,类似于在表达式上创建索引,但它们避免了索引维护的开销。为统计对象定义中的每个表达式自动构建表达式统计。
# 例子
创建表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);
如果没有功能依赖统计,规划者会假设这两个在哪里
条件是独立的,并且会将它们的选择性相乘以得出一个非常小的行数估计值。有了这样的统计数据,规划者认识到在哪里
条件是冗余的,不会低估行数。
创建表格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
并使用该列上的表达式运行查询。如果没有扩展的统计信息,规划器就没有关于表达式的数据分布的信息,而是使用默认估计值。规划者也没有意识到,截短到月份的日期的值完全由截短到当天的日期的值决定。然后,表达式和NDistint统计信息建立在这两个表达式的基础上:
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%的选择性,并且表达式中的不同值的数量与列中的相同(即唯一)。这导致在前两个查询中严重低估了行数。此外,规划者没有关于表达式之间关系的信息,因此它假定这两个表达式哪里
和分组
条件是独立的,并将它们的选择性相乘,从而得出聚合查询中严重高估的组数。由于表达式缺乏准确的统计信息,这进一步加剧了这种情况,迫使计划者对从列的ndistinct派生的表达式使用默认的ndistinct估计值。有了这些统计数据,规划者认识到这些条件是相互关联的,并得出更准确的估计。
# 兼容性
没有创建统计数据
SQL标准中的命令。