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
。统计信息会在下次访问表时再次收集。