ANALYZE
=====

收集数据库的统计信息。


---

语法
--------

```sql
ANALYZE [VERBOSE] [ (SKIP_LOCKED) ] [<table> [ (<column> [, ...] ) ]]
```


---

描述
----------


`ANALYZE` 收集数据库表中的内容统计信息，并将结果存储在系统表 `pg_statistic` 中。后续操作中，MAXIR 会使用这些统计信息来帮助确定查询的最有效的执行计划。有关收集的表统计信息，请参见[使用注意事项](#使用注意事项)。

如果没有参数，`ANALYZE` 将收集当前数据库中每个表的统计信息。你可以指定表名来收集单个表的统计信息。你可以在特定表中指定一组列名，这样只会收集来自该表的这些列的统计信息。

`ANALYZE` 不收集外部表的统计信息。


---

参数
----------


- **`VERBOSE`**

    启用显示进度消息。当指定该选项时，`ANALYZE` 发出以下信息：
    
    - 正在处理的表。

    - 用于生成样本表的查询。

    - 正在计算统计信息的列。

    - 为单列收集不同统计信息的查询。

    - 收集的统计信息。

- **`SKIP_LOCKED`**

    指定 `ANALYZE` 在开始处理表时不等待任何冲突锁被释放：如果不能立即锁定表而不等待，它将跳过该表。请注意，即使有此选项，`ANALYZE` 在打开表的索引或从表继承子表获取样本行时仍可能产生阻塞。

- _`<table>`_

    表的名称，支持使用 Schema 名称进行限定。如不提供该参数，当前数据库中的所有常规表都会被分析。

- _`<column>`_

    要分析列的名称。如果不指定该参数，表中的所有列都会被分析。


---

使用注意事项
--------

推荐定期运行 `ANALYZE` 或在对表内容进行重大更改后运行 `ANALYZE`。准确的统计信息可以帮助 MAXIR 选择最合适的查询计划，从而提高查询处理的速度。对于读密集型数据库，你可以在业务低峰期运行 `VACUUM` 和 `ANALYZE`。（不适用于涉及大量更新活动的场景。）你可以使用位于 `gp_toolkit` Schema 中的 `gp_stats_missing` 视图检查缺少统计信息的表：

```sql
SELECT * FROM gp_toolkit.gp_stats_missing;
```

`ANALYZE` 需要获取目标表上的 `SHARE UPDATE EXCLUSIVE` 锁。此锁与 `SHARE UPDATE EXCLUSIVE`、`SHARE`、`SHARE ROW EXCLUSIVE`、`EXCLUSIVE` 和 `ACCESS EXCLUSIVE` 锁冲突。

如果你在一个不包含数据的表上运行 `ANALYZE`，则不会收集该表的统计信息。例如，如果你对具有统计信息的表执行 `TRUNCATE` 操作，然后在该表上运行 `ANALYZE`，则统计信息不会改变。

`ANALYZE` 收集的统计信息通常包括每列中一些最常见值的列表，以及一个显示每列近似数据分布的直方图。如果 `ANALYZE` 认为这些信息不重要（例如，对于唯一键列，没有常见值）或者列的数据类型不支持相关操作符，这两者都可能被省略。


对于大型表，`ANALYZE` 会随机抽取表中的样本数据，而非逐行检查。这使得即使是非常大的表也能在较短时间内完成分析。然而，需要注意的是，统计信息仅为近似值，即便表的实际内容没有发生变化，每次运行 `ANALYZE` 时统计结果可能略有不同。这可能导致查询计划器在 `EXPLAIN` 中显示的估算成本发生轻微变化。在极少数情况下，这种非确定性可能导致查询优化器在不同的 `ANALYZE` 执行之间选择不同的查询计划。为避免这种情况，可以通过调整 `default_statistics_target` 配置参数增加 `ANALYZE` 收集的统计数据量，或者通过 `ALTER TABLE ... ALTER COLUMN ... SET (n_distinct ...)` 为各列单独设置统计目标（详见 [ALTER TABLE](/docs/maxir/Reference_Manual/sql-commands/alter-table)）。该目标值决定了最常见值列表中的最大条目数和直方图中的最大区间数。默认目标值为 100，但可以根据需要进行调整，以在计划器估算的准确性、`ANALYZE` 执行时间及 `pg_statistic` 中占用的存储空间之间做出权衡。尤其是，将统计目标设置为零会禁用对该列的统计信息收集。对于从未在查询的 `WHERE`、`GROUP BY` 或 `ORDER BY` 子句中使用的列，这可能是有益的，因为计划器无需这些列的统计信息。

在被分析的列中的最大统计目标确定准备统计信息的表行的数量。增加目标会导致 `ANALYZE` 所需的时间和空间成比例增加。

`ANALYZE` 估计的一个值是每列中出现的不同值的数量。因为只有部分行被检查，即使在最大可能的统计目标下，这个估计有时也可能相当不准确。

当 MAXIR 执行 `ANALYZE` 操作来收集表的统计信息，并检测到所有抽样的表数据页都是空的（不包含有效数据）时，MAXIR 会显示应该执行 `VACUUM FULL` 操作的消息。如果抽样页面为空，则表统计信息将不准确。在对表进行大量更改后，页面会变为空，例如删除大量行。`VACUUM FULL` 操作会删除空页面，允许 `ANALYZE` 操作收集准确的统计信息。


如果表没有统计信息，则通过服务器配置参数 `gp_enable_relsize_collection` 来控制 Postgres Planner 是使用默认的统计文件还是通过 `pg_relation_size` 函数估算表的大小。默认情况下，如果没有统计信息，Postgres Planner 会使用默认的统计文件来估算行数。


---

示例
--------

收集表 `sales` 的统计信息：

```sql
ANALYZE sales;
```

---

SQL 标准兼容性
-------------

标准 SQL 中没有 `ANALYZE` 语句。
