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]
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
withUPDATE HISTOGRAM
子句为指定的表列生成直方图统计信息并将它们存储在数据字典中。此语法只允许使用一个表名。MySQL 8.0.31 及之后的版本也支持将单列的直方图设置为用户自定义的 JSON 值。ANALYZE TABLE
withDROP 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
用来分析一个或多个分区;有关详细信息,请参阅第 13.1.9 节,“ALTER TABLE 语句”和
第 24.3.4 节,“分区维护”。
在分析过程中,表被 和 的读锁
InnoDB
锁定MyISAM
。
ANALYZE TABLE
从表定义缓存中删除表,这需要刷新锁。如果有长时间运行的语句或事务仍在使用该表,则后续语句和事务必须等待这些操作完成才能释放刷新锁。因为ANALYZE TABLE
它本身通常很快完成,所以涉及同一个表的延迟事务或语句可能并不明显是由于剩余的刷新锁。
默认情况下,服务器将ANALYZE
TABLE
语句写入二进制日志,以便它们复制到副本。要禁止记录日志,请指定可选
NO_WRITE_TO_BINLOG
关键字或其别名
LOCAL
。
ANALYZE TABLE
返回一个结果集,其列如下表所示。
柱子 | 价值 |
---|---|
Table |
表名 |
Op |
analyze 或者histogram |
Msg_type |
status , error ,
info ,note 或
warning |
Msg_text |
信息性消息 |
ANALYZE TABLE
没有任何一个
HISTOGRAM
子句执行密钥分布分析并存储一个或多个表的分布。任何现有的直方图统计数据不受影响。
如果自上次键分布分析以来该表未发生变化,则不会再次分析该表。
MySQL 使用存储的键分布来决定表的连接顺序,以便连接常量以外的东西。此外,在决定将哪些索引用于查询中的特定表时,可以使用键分布。
要检查存储的密钥分布基数,请使用
SHOW INDEX
语句或
INFORMATION_SCHEMA
STATISTICS
表。请参阅
第 13.7.7.22 节,“SHOW INDEX 语句”和
第 26.3.34 节,“INFORMATION_SCHEMA STATISTICS 表”。
对于InnoDB
表,
ANALYZE TABLE
通过对每个索引树执行随机潜水并相应地更新索引基数估计来确定索引基数。因为这些只是估计值,重复运行
ANALYZE TABLE
可能会产生不同的数字。这使得表格ANALYZE
TABLE
速度很快InnoDB
但不是 100% 准确,因为它没有考虑所有行。
您可以
通过启用使收集
的统计信息ANALYZE TABLE
更精确、更稳定
innodb_stats_persistent
,如第 15.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
,请参阅
第 15.8.10.1 节,“配置持久优化器统计参数”和
第 15.8.10.3 节,“估计 InnoDB 表的分析表复杂性”。
MySQL 在连接优化中使用索引基数估计。如果连接未以正确的方式优化,请尝试运行
ANALYZE TABLE
. 在少数情况下,ANALYZE TABLE
您的特定表不能产生足够好的值,您可以使用FORCE INDEX
查询来强制使用特定索引,或设置
max_seeks_for_key
系统变量以确保 MySQL 更喜欢索引查找而不是表扫描。请参阅第 B.3.5 节,“与优化器相关的问题”。
ANALYZE TABLE
with
HISTOGRAM
子句可以管理表列值的直方图统计信息。有关直方图统计的信息,请参阅
第 8.9.6 节,“优化器统计”。
这些直方图操作可用:
ANALYZE TABLE
withUPDATE HISTOGRAM
子句为指定的表列生成直方图统计信息并将它们存储在数据字典中。此语法只允许使用一个表名。可选子句指定直方图的桶数。取值 必须是1到1024之间的整数。如果省略该子句,则桶数为100。
WITH
N
BUCKETSN
ANALYZE TABLE
withDROP HISTOGRAM
子句从数据字典中删除指定表列的直方图统计信息。此语法只允许使用一个表名。
存储直方图管理语句只影响命名列。考虑这些陈述:
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
不受影响。
在构建直方图的过程中对用户数据进行采样时,不会读取所有值;这可能会导致丢失一些被认为重要的值。在这种情况下,修改直方图或根据您自己的标准(例如完整数据集)明确设置您自己的直方图可能很有用。MySQL 8.0.31 添加了对更新直方图表列的支持,其中提供的数据与用于显示信息模式表中
的列值的
JSON 格式相同。使用 JSON 数据更新直方图时只能修改一列。
ANALYZE TABLE
tbl_name
UPDATE HISTOGRAM ON
col_name
USING DATA
'json_data
'HISTOGRAM
COLUMN_STATISTICS
我们可以通过首先在
tableUSING DATA
的列上生成直方图来说明 的用法,如下所示:
c1
t
mysql> ANALYZE TABLE t UPDATE HISTOGRAM ON c1;
+--------+-----------+----------+-----------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------+-----------+----------+-----------------------------------------------+
| mydb.t | histogram | status | Histogram statistics created for column 'c1'. |
+--------+-----------+----------+-----------------------------------------------+
我们可以在
COLUMN_STATISTICS
表中看到生成的直方图:
mysql> TABLE information_schema.column_statistics\G
*************************** 1. row ***************************
SCHEMA_NAME: mydb
TABLE_NAME: t
COLUMN_NAME: c1
HISTOGRAM: {"buckets": [[206, 0.0625], [456, 0.125], [608, 0.1875]],
"data-type": "int", "null-values": 0.0, "collation-id": 8, "last-updated":
"2022-10-11 16:13:14.563319", "sampling-rate": 1.0, "histogram-type":
"singleton", "number-of-buckets-specified": 100}
现在我们放下直方图,当我们检查时
COLUMN_STATISTICS
,它现在是空的:
mysql> ANALYZE TABLE t DROP HISTOGRAM ON c1;
+--------+-----------+----------+-----------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------+-----------+----------+-----------------------------------------------+
| mydb.t | histogram | status | Histogram statistics removed for column 'c1'. |
+--------+-----------+----------+-----------------------------------------------+
mysql> TABLE information_schema.column_statistics\G
Empty set (0.00 sec)
我们可以通过插入之前从表的
HISTOGRAM
列中
获得的 JSON 表示来恢复删除的直方图COLUMN_STATISTICS
,当我们再次查询该表时,我们可以看到直方图已经恢复到之前的状态:
mysql> ANALYZE TABLE t UPDATE HISTOGRAM ON c1
-> USING DATA '{"buckets": [[206, 0.0625], [456, 0.125], [608, 0.1875]],
-> "data-type": "int", "null-values": 0.0, "collation-id":
-> 8, "last-updated": "2022-10-11 16:13:14.563319",
-> "sampling-rate": 1.0, "histogram-type": "singleton",
-> "number-of-buckets-specified": 100}';
+--------+-----------+----------+-----------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------+-----------+----------+-----------------------------------------------+
| mydb.t | histogram | status | Histogram statistics created for column 'c1'. |
+--------+-----------+----------+-----------------------------------------------+
mysql> TABLE information_schema.column_statistics\G
*************************** 1. row ***************************
SCHEMA_NAME: mydb
TABLE_NAME: t
COLUMN_NAME: c1
HISTOGRAM: {"buckets": [[206, 0.0625], [456, 0.125], [608, 0.1875]],
"data-type": "int", "null-values": 0.0, "collation-id": 8, "last-updated":
"2022-10-11 16:13:14.563319", "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
值需要足够的权限来设置受限会话系统变量。请参阅
第 5.1.9.1 节,“系统变量权限”。
如果为生成直方图而读入内存的估计数据量超过了定义的限制
histogram_generation_max_mem_size
,MySQL 将对数据进行采样,而不是将其全部读入内存。采样均匀分布在整个表上。MySQL使用SYSTEM
采样,这是一种页面级别的采样方法。
可以查询表列中
的sampling-rate
值
以确定为创建直方图而采样的数据分数。是介于 0.0 和 1.0 之间的数字。
值 1 表示已读取所有数据(无采样)。
HISTOGRAM
INFORMATION_SCHEMA.COLUMN_STATISTICS
sampling-rate
以下示例演示了采样。为了确保数据量超过
histogram_generation_max_mem_size
示例的限制,在为表的birth_date
列
生成直方图统计信息之前,将限制设置为较低的值(2000000 字节) employees
。
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 表示该
birth_date
列中大约 4.9% 的数据被读入内存以生成直方图统计信息。
从 MySQL 8.0.19 开始,存储引擎为存储在表InnoDB
中的数据提供了自己的采样实现。InnoDB
当存储引擎不提供自己的存储引擎时,MySQL 使用的默认采样实现需要全表扫描,这对于大表来说代价高昂。InnoDB
采样实现通过避免全表扫描来提高采样性能
。
sampled_pages_read
和
sampled_pages_skipped
INNODB_METRICS
计数器可用于监视InnoDB
数据页
的采样。(有关一般
INNODB_METRICS
计数器使用信息,请参阅
第 26.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)
基于采样计数器数据的采样率与表中列中
的sampling-rate
值
大致相同
。
HISTOGRAM
INFORMATION_SCHEMA.COLUMN_STATISTICS
有关为直方图生成执行的内存分配的信息,请监控 Performance Schema
memory/sql/histograms
工具。请参阅
第 27.12.20.10 节,“内存汇总表”。
ANALYZE TABLE
从表中清除表统计信息
INFORMATION_SCHEMA.INNODB_TABLESTATS
并将STATS_INITIALIZED
列设置为Uninitialized
。下次访问表时会再次收集统计信息。