2025年9月25日: PostgreSQL 18 釋出!
支援版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10

CREATE STATISTICS

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

描述

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% 的選擇性,並且表示式的唯一值數量被假定與列的唯一值數量相同(即唯一)。這導致前兩個查詢的行數估算顯著偏低。此外,規劃器對錶達式之間的關係沒有資訊,因此它假設兩個 WHEREGROUP BY 條件是獨立的,並將它們選擇性相乘,從而導致聚合查詢的組計數嚴重高估。這由於表示式缺乏準確的統計資訊而進一步加劇,迫使規劃器使用從列的 ndistinct 估算派生的表示式的預設 ndistinct 估算。有了這樣的統計資訊,規劃器就能識別出這些條件是相關的,並得到更準確的估算。

相容性

SQL 標準中沒有 CREATE STATISTICS 命令。

提交更正

如果您在文件中發現任何不正確、與您對特定功能的使用體驗不符或需要進一步澄清的內容,請使用 此表格 報告文件問題。