文档主页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
信息 (Gzip) - 4.0Mb
信息 (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  ANALYZE TABLE 语句

15.7.3.1 ANALYZE TABLE 语句

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
    TABLE tbl_name [, tbl_name] ...

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
    TABLE tbl_name
    UPDATE HISTOGRAM ON col_name [, col_name] ...
        [WITH N BUCKETS]
    [{MANUAL | AUTO} UPDATE]

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL] 
    TABLE tbl_name
    UPDATE HISTOGRAM ON col_name [USING DATA 'json_data']

ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]
    TABLE tbl_name
    DROP HISTOGRAM ON col_name [, col_name] ...

ANALYZE TABLE 生成表统计信息

  • ANALYZE TABLEHISTOGRAM 子句执行密钥分布分析并存储命名表或表的分布。对于 MyISAM 表,ANALYZE TABLE 用于密钥分布分析等效于使用 myisamchk --analyze.

  • ANALYZE TABLEUPDATE HISTOGRAM 子句为命名表列生成直方图统计信息并将其存储在数据字典中。这种语法只允许使用一个表名。MySQL 还支持将单个列的直方图设置为用户定义的 JSON 值。

  • ANALYZE TABLEDROP HISTOGRAM 子句从数据字典中删除命名表列的直方图统计信息。这种语法只允许使用一个表名。

此语句需要表级的 SELECTINSERT 权限。

ANALYZE TABLEInnoDBNDBMyISAM 表一起使用。它不适用于视图。

如果 innodb_read_only 系统变量已启用,ANALYZE TABLE 可能会失败,因为它无法更新数据字典中的统计表,这些统计表使用 InnoDB。对于更新键分布的 ANALYZE TABLE 操作,即使操作更新了表本身(例如,如果它是一个 MyISAM 表),也可能会发生故障。要获取更新的分布统计信息,请设置 information_schema_stats_expiry=0

ANALYZE TABLE 支持分区表,您可以使用 ALTER TABLE ... ANALYZE PARTITION 分析一个或多个分区;有关更多信息,请参见 第 15.1.9 节,“ALTER TABLE 语句”第 26.3.4 节,“分区维护”

在分析期间,表将使用读取锁锁定,用于 InnoDBMyISAM

默认情况下,服务器将 ANALYZE TABLE 语句写入二进制日志,以便它们复制到副本。要抑制日志记录,请指定可选的 NO_WRITE_TO_BINLOG 关键字或其别名 LOCAL

ANALYZE TABLE 输出

ANALYZE TABLE 返回一个结果集,其中包含下表中显示的列。

表名
Op analyzehistogram
Msg_type statuserrorinfonotewarning
Msg_text 一条信息消息
键分布分析

没有 HISTOGRAM 子句的 ANALYZE TABLE 会执行键分布分析并存储表的分布。任何现有的直方图统计信息保持不变。

如果表自上次键分布分析以来没有更改,则不会再次分析该表。

MySQL 使用存储的键分布来决定按什么顺序连接表,以连接非常数的内容。此外,在决定为查询中的特定表使用哪个索引时,可以使用键分布。

要检查存储的键分布基数,请使用 SHOW INDEX 语句或 INFORMATION_SCHEMA STATISTICS 表。请参见 第 15.7.7.23 节,“SHOW INDEX 语句”第 28.3.34 节,“INFORMATION_SCHEMA STATISTICS 表”

对于 InnoDB 表,ANALYZE TABLE 通过对每个索引树执行随机潜水来确定索引基数,并相应地更新索引基数估计值。由于这些只是估计值,因此多次运行 ANALYZE TABLE 可能会产生不同的数字。这使得 ANALYZE TABLEInnoDB 表上速度很快,但不是 100% 准确,因为它没有考虑所有行。

您可以通过启用 innodb_stats_persistent 来使 ANALYZE TABLE 收集的 统计信息 更精确、更稳定,如 第 17.8.10.1 节,“配置持久优化器统计信息参数” 中所述。当 innodb_stats_persistent 启用时,在对索引列数据进行重大更改后运行 ANALYZE TABLE 很重要,因为统计信息不会定期重新计算(例如,在服务器重启后)。

如果 innodb_stats_persistent 已启用,您可以通过修改 innodb_stats_persistent_sample_pages 系统变量来更改随机潜水的数量。如果 innodb_stats_persistent 已禁用,则改为修改 innodb_stats_transient_sample_pages

有关 InnoDB 中键分布分析的更多信息,请参见 第 17.8.10.1 节,“配置持久优化器统计信息参数”第 17.8.10.3 节,“估计 InnoDB 表的 ANALYZE TABLE 复杂度”

MySQL 在连接优化中使用索引基数估计值。如果连接没有以正确的方式进行优化,请尝试运行 ANALYZE TABLE。在极少数情况下,ANALYZE TABLE 无法生成适合您特定表的足够好的值,您可以对查询使用 FORCE INDEX 来强制使用特定索引,或者设置 max_seeks_for_key 系统变量以确保 MySQL 更喜欢索引查找而不是表扫描。请参见 第 B.3.5 节,“与优化器相关的問題”

直方图统计分析

带有 HISTOGRAM 子句的 ANALYZE TABLE 允许管理表列值的直方图统计信息。有关直方图统计信息的更多信息,请参见 第 10.9.6 节,“优化器统计信息”

这些直方图操作可用

  • 带有 UPDATE HISTOGRAM 子句的 ANALYZE TABLE 为指定的表列生成直方图统计信息,并将它们存储在数据字典中。此语法仅允许一个表名。

    可选的 WITH N BUCKETS 子句指定直方图的桶数。N 的值必须是 1 到 1024 之间的整数。如果省略此子句,则桶数为 100。

    可选的 AUTO UPDATE 子句启用表的直方图自动更新。启用后,此表的 ANALYZE TABLE 语句会自动更新直方图,使用上次由 WITH ... BUCKETS 指定的相同桶数(如果先前已为此表设置)。此外,在重新计算表的持久统计信息时(请参见 第 17.8.10.1 节,“配置持久优化器统计信息参数”),InnoDB 后台统计信息线程也会更新直方图。MANUAL UPDATE 禁用自动更新,是未指定时的默认设置。

  • 带有 DROP HISTOGRAM 子句的 ANALYZE TABLE 从数据字典中删除指定的表列的直方图统计信息。此语法仅允许一个表名。

存储的直方图管理语句仅影响指定的列。请考虑以下语句

ANALYZE TABLE t UPDATE HISTOGRAM ON c1, c2, c3 WITH 10 BUCKETS;
ANALYZE TABLE t UPDATE HISTOGRAM ON c1, c3 WITH 10 BUCKETS;
ANALYZE TABLE t DROP HISTOGRAM ON c2;

第一个语句更新 c1c2c3 列的直方图,替换这些列的任何现有直方图。第二个语句更新 c1c3 的直方图,使 c2 的直方图保持不变。第三个语句删除 c2 的直方图,使 c1c3 的直方图保持不变。

在将用户数据采样为构建直方图的一部分时,不会读取所有值;这可能会导致遗漏一些被认为重要的值。在这种情况下,修改直方图或根据自己的标准明确设置自己的直方图可能会有用,例如完整的​​数据集。ANALYZE TABLE tbl_name UPDATE HISTOGRAM ON col_name USING DATA 'json_data' 使用与从 Information Schema COLUMN_STATISTICS 表中显示 HISTOGRAM 列值所用相同的 JSON 格式提供的​​数据来更新直方图表的一列。使用 JSON 数据更新直方图时,只能修改一列。

我们可以通过首先在表 tc1 列上生成直方图来说明 USING DATA 的用法,如下所示

mysql> ANALYZE TABLE t UPDATE HISTOGRAM ON c1;
+-------+-----------+----------+-----------------------------------------------+
| Table | Op        | Msg_type | Msg_text                                      |
+-------+-----------+----------+-----------------------------------------------+
| h.t   | histogram | status   | Histogram statistics created for column 'c1'. |
+-------+-----------+----------+-----------------------------------------------+
1 row in set (0.00 sec)

我们可以在 COLUMN_STATISTICS 表中看到生成的直方图

mysql> TABLE information_schema.column_statistics\G
*************************** 1. row ***************************
SCHEMA_NAME: h
 TABLE_NAME: t
COLUMN_NAME: c1
  HISTOGRAM: {"buckets": [], "data-type": "int", "auto-update": false,
"null-values": 0.0, "collation-id": 8, "last-updated": "2024-03-26
16:54:43.674995", "sampling-rate": 1.0, "histogram-type": "singleton",
"number-of-buckets-specified": 100}   
1 row in set (0.00 sec)

现在我们删除直方图,当我们检查 COLUMN_STATISTICS 时,它为空

mysql> ANALYZE TABLE t DROP HISTOGRAM ON c1;
+-------+-----------+----------+-----------------------------------------------+
| Table | Op        | Msg_type | Msg_text                                      |
+-------+-----------+----------+-----------------------------------------------+
| h.t   | histogram | status   | Histogram statistics removed for column 'c1'. |
+-------+-----------+----------+-----------------------------------------------+
1 row in set (0.01 sec)

mysql> TABLE information_schema.column_statistics\G
Empty set (0.00 sec)

我们可以通过插入先前从 COLUMN_STATISTICS 表的 HISTOGRAM 列中获取的 JSON 表示来恢复已删除的直方图,当我们再次查询该表时,我们可以看到直方图已恢复到其先前状态

mysql> ANALYZE TABLE t UPDATE HISTOGRAM ON c1 
    ->     USING DATA '{"buckets": [], "data-type": "int", "auto-update": false,
    ->               "null-values": 0.0, "collation-id": 8, "last-updated": "2024-03-26
    ->               16:54:43.674995", "sampling-rate": 1.0, "histogram-type": "singleton",
    ->               "number-of-buckets-specified": 100}';   
+-------+-----------+----------+-----------------------------------------------+
| Table | Op        | Msg_type | Msg_text                                      |
+-------+-----------+----------+-----------------------------------------------+
| h.t   | histogram | status   | Histogram statistics created for column 'c1'. |
+-------+-----------+----------+-----------------------------------------------+

mysql> TABLE information_schema.column_statistics\G
*************************** 1. row ***************************
SCHEMA_NAME: h
 TABLE_NAME: t
COLUMN_NAME: c1
  HISTOGRAM: {"buckets": [], "data-type": "int", "auto-update": false,
"null-values": 0.0, "collation-id": 8, "last-updated": "2024-03-26
16:54:43.674995", "sampling-rate": 1.0, "histogram-type": "singleton",
"number-of-buckets-specified": 100}

直方图生成不支持加密表(以避免在统计信息中暴露数据)或 TEMPORARY 表。

直方图生成适用于除几何类型(空间数据)和 JSON 以外的所有数据类型的列。

可以为存储的和虚拟生成的列生成直方图。

无法为由单列唯一索引覆盖的列生成直方图。

直方图管理语句会尝试执行尽可能多的请求的操作,并为其余部分报告诊断消息。例如,如果 UPDATE HISTOGRAM 语句命名了多个列,但其中一些列不存在或具有不受支持的数据类型,则会为其他列生成直方图,并为无效列生成消息。

直方图受以下 DDL 语句影响

  • DROP TABLE 删除已删除表中列的直方图。

  • DROP DATABASE 删除已删除数据库中任何表的直方图,因为该语句会删除数据库中的所有表。

  • RENAME TABLE 不会删除直方图。相反,它会重命名重命名表的直方图,使其与新的表名相关联。

  • ALTER TABLE 语句删除或修改列会删除该列的直方图。

  • ALTER TABLE ... CONVERT TO CHARACTER SET 会删除字符列的直方图,因为它们会受到字符集更改的影响。非字符列的直方图不受影响。

histogram_generation_max_mem_size 系统变量控制直方图生成可用的最大内存量。可以在运行时设置全局和会话值。

更改全局 histogram_generation_max_mem_size 值需要足够的权限来设置全局系统变量。更改会话 histogram_generation_max_mem_size 值需要足够的权限来设置受限会话系统变量。请参见 第 7.1.9.1 节“系统变量权限”

如果要读入内存以进行直方图生成的估计数据量超过了 histogram_generation_max_mem_size 定义的限制,MySQL 会对数据进行采样,而不是将所有数据读入内存。采样均匀分布在整个表中。MySQL 使用 SYSTEM 采样,这是一种页面级采样方法。

Information Schema COLUMN_STATISTICS 表中 HISTOGRAM 列的 sampling-rate 值可以查询,以确定用于创建直方图的采样数据比例。 sampling-rate 是介于 0.0 和 1.0 之间的数字。值为 1 表示读取了所有数据(没有采样)。

以下示例演示了采样。为了确保数据量超过 histogram_generation_max_mem_size 限制(用于示例目的),该限制在为 employees 表的 birth_date 列生成直方图统计信息之前被设置为较低的值(2000000 字节)。

mysql> SET histogram_generation_max_mem_size = 2000000;

mysql> USE employees;

mysql> ANALYZE TABLE employees UPDATE HISTOGRAM ON birth_date WITH 16 BUCKETS\G
*************************** 1. row ***************************
   Table: employees.employees
      Op: histogram
Msg_type: status
Msg_text: Histogram statistics created for column 'birth_date'.

mysql> SELECT HISTOGRAM->>'$."sampling-rate"'
       FROM INFORMATION_SCHEMA.COLUMN_STATISTICS
       WHERE TABLE_NAME = "employees"
       AND COLUMN_NAME = "birth_date";
+---------------------------------+
| HISTOGRAM->>'$."sampling-rate"' |
+---------------------------------+
| 0.0491431208869665              |
+---------------------------------+

sampling-rate 值为 0.0491431208869665 表示大约 4.9% 的 birth_date 列数据被读入内存以生成直方图统计信息。

InnoDB 存储引擎为存储在 InnoDB 表中的数据提供了自己的采样实现。MySQL 在存储引擎不提供自己的采样实现时使用的默认采样实现需要进行全表扫描,对于大型表来说成本很高。 InnoDB 采样实现通过避免全表扫描来提高采样性能。

sampled_pages_readsampled_pages_skipped INNODB_METRICS 计数器可用于监控 InnoDB 数据页面的采样。(有关一般 INNODB_METRICS 计数器使用信息,请参见 第 28.4.21 节“INFORMATION_SCHEMA INNODB_METRICS 表”。)

以下示例演示了采样计数器使用,这需要在生成直方图统计信息之前启用计数器。

mysql> SET GLOBAL innodb_monitor_enable = 'sampled%';

mysql> USE employees;

mysql> ANALYZE TABLE employees UPDATE HISTOGRAM ON birth_date WITH 16 BUCKETS\G
*************************** 1. row ***************************
   Table: employees.employees
      Op: histogram
Msg_type: status
Msg_text: Histogram statistics created for column 'birth_date'.

mysql> USE INFORMATION_SCHEMA;

mysql> SELECT NAME, COUNT FROM INNODB_METRICS WHERE NAME LIKE 'sampled%'\G
*************************** 1. row ***************************
 NAME: sampled_pages_read
COUNT: 43
*************************** 2. row ***************************
 NAME: sampled_pages_skipped
COUNT: 843

此公式根据采样计数器数据近似地计算采样率。

sampling rate = sampled_page_read/(sampled_pages_read + sampled_pages_skipped)

根据采样计数器数据计算的采样率与 Information Schema COLUMN_STATISTICS 表中 HISTOGRAM 列的 sampling-rate 值大致相同。

有关为直方图生成而执行的内存分配信息,请监控 Performance Schema memory/sql/histograms 仪器。请参见 第 29.12.20.10 节“内存摘要表”

其他注意事项

ANALYZE TABLE 会清除 Information Schema INNODB_TABLESTATS 表中的表统计信息,并将 STATS_INITIALIZED 列设置为 Uninitialized。下次访问该表时将再次收集统计信息。