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 TABLE
无HISTOGRAM
子句执行密钥分布分析并存储命名表或表的分布。对于MyISAM
表,ANALYZE TABLE
用于密钥分布分析等效于使用 myisamchk --analyze.ANALYZE TABLE
带UPDATE HISTOGRAM
子句为命名表列生成直方图统计信息并将其存储在数据字典中。这种语法只允许使用一个表名。MySQL 还支持将单个列的直方图设置为用户定义的 JSON 值。ANALYZE TABLE
带DROP HISTOGRAM
子句从数据字典中删除命名表列的直方图统计信息。这种语法只允许使用一个表名。
ANALYZE TABLE
与 InnoDB
、NDB
和 MyISAM
表一起使用。它不适用于视图。
如果 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 节,“分区维护”。
在分析期间,表将使用读取锁锁定,用于 InnoDB
和 MyISAM
。
默认情况下,服务器将 ANALYZE TABLE
语句写入二进制日志,以便它们复制到副本。要抑制日志记录,请指定可选的 NO_WRITE_TO_BINLOG
关键字或其别名 LOCAL
。
ANALYZE TABLE
返回一个结果集,其中包含下表中显示的列。
列 | 值 |
---|---|
表 |
表名 |
Op |
analyze 或 histogram |
Msg_type |
status 、error 、info 、note 或 warning |
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 TABLE
在 InnoDB
表上速度很快,但不是 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
BUCKETSN
的值必须是 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;
第一个语句更新 c1
、c2
和 c3
列的直方图,替换这些列的任何现有直方图。第二个语句更新 c1
和 c3
的直方图,使 c2
的直方图保持不变。第三个语句删除 c2
的直方图,使 c1
和 c3
的直方图保持不变。
在将用户数据采样为构建直方图的一部分时,不会读取所有值;这可能会导致遗漏一些被认为重要的值。在这种情况下,修改直方图或根据自己的标准明确设置自己的直方图可能会有用,例如完整的数据集。ANALYZE TABLE
使用与从 Information Schema tbl_name
UPDATE HISTOGRAM ON col_name
USING DATA 'json_data
'COLUMN_STATISTICS
表中显示 HISTOGRAM
列值所用相同的 JSON 格式提供的数据来更新直方图表的一列。使用 JSON 数据更新直方图时,只能修改一列。
我们可以通过首先在表 t
的 c1
列上生成直方图来说明 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_read
和 sampled_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
。下次访问该表时将再次收集统计信息。