统计信息是啥? 对表(索引)的信息的统计. 有对表(索引)级统计的, 比如有多少行数据,平均行长度; 也有针对某些字段的更具体的统计(直方图), 比如a字段在某个范围有多少条,占比多少.
统计信息有啥用? 优化器需要知道表的基础信息从而生成相关的执行计划.
什么时候收集统计信息?
自动收集:
手动收集:
怎么收集统计信息 使用analyze table tblname
即可收集表的统计信息. 完整语法如下:
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] ..
收集的统计信息放哪的?
我们再来看统计信息相关的参数和表吧:
参数 | 描述 | 默认值 |
---|---|---|
innodb_stats_auto_recalc | 是否自动收集统计信息 | ON |
innodb_stats_include_delete_marked | 被标记为删除的行是否要计算 (默认off) | off |
innodb_stats_method | 关于null的计算, 默认nulls_equal, 即null都算一个 | nulls_equal |
innodb_stats_on_metadata | 未开启统计信息持久化时,对于执行show table status之类查看元数据信息时是否更新统计信息 | off |
innodb_stats_persistent | 统计信息是否持久化 | on |
innodb_stats_persistent_sample_pages | 统计信息持久化时,每次采样多少 | 20 |
innodb_stats_transient_sample_pages | 统计信息未开启持久化时,每次采样多少 | 8 |
innodb_stats_persistent表示是否持久化统计信息到磁盘(表), 默认:ON
若为OFF: 表示仅存放在内存中, 重启后就没了, 只有下次访问的时候才会重新收集
若为ON: 则还会存储到系统表中:
database_name: 该表对应的数据库名
table_name: 表名/分区名/子分区名
last_update: 收集统计信息的时间
n_rows: 有多少行数据
clustered_index_size: 主键索引的总大小,单位:page.
sum_of_other_index_sizes: 其它索引的大小,单位:page
database_name: 该表对应的数据库名
table_name: 表名/分区名/子分区名
index_name: 索引名
last_update: 统计信息收集时间
stat_name:
若为size,则stat_value表示该索引的总页数;
若为n_leaf_pages,则stat_value表示该索引的叶子节点数量
若为n_diff_pfx, 则stat_value表示该索引的该字段有多少行
sample_size: 采样数量(page), 默认20, 我这里是设置表级别的STATS_SAMPLE_PAGES=65535
stat_description: 描述信息, 方便理解改行内容的
我们无法直接查询mysql.column_statistics,
但是我们可以查询视图information_schema.COLUMN_STATISTICS
这里涉及到buckets(桶), 也就是'直方图'有多少'方', 默认100, 范围是1-1024. 说白了就是把这一列数据分为多少份.
除了修改参数, 我们还可以指定表级别的属性来控制是否收集统计信息.
create table db1.t20250816_statistics(
id int
) stats_auto_recalc=1 stats_sample_pages=200 stats_persistent=1;
stats_auto_recalc 是否自动收集,
stats_sample_pages 每次收集时采样多少
stats_persistent 是否持久化
这里有个没卵用的细节, 在sdi信息中, stats_auto_recalc 0:不显示, 1:启用 2: 禁用
启用持久化统计信息时,是否自动收集统计信息 若启用, 则在数据量变化10%或者create/alter table
时自动收集统计信息.
若未启用持久化统计信息时, 则每次收集(比如analyze table)多少页. 默认是8页.
若启用持久化统计信息时, 每次收集多少页(叶子节点), 默认是20, 上限是18446744073709551615,
表级别的上限是65535. 不然会报错
ERROR 1064 (42000): The valid range for stats_sample_pages is [1, 65535]. Error near '200000 stats_persistent=1' at line 1
若未开启持久化统计信息,访问元数据信息时,是否更新统计信息: 若启用该参数(默认未启用),执行show table status,或者访问 information_schema.tables/statistics时会自动更新统计信息
收集统计信息时, 被标记为deleted的数据是否还要计算在内. 默认off,即删除的数据不考虑
主要是关于null的统计策略
nulls_equal(默认): null的一共算一个
nulls_unequal: null的每个都单独计算
nulls_ignored: null的一个都不算, 全部跳过
简单的讲解了下统计信息相关的变量, 部分变量存在依赖关系, 大概如下图:
参考:
https://dev.mysql.com/doc/refman/8.0/en/innodb-persistent-stats.html
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。