数据库的统计信息非常重要。它对于优化器制定准确的执行计划,有着非常重要的意义。通常在我们考虑优化之前,都需要先查看相关对象的统计信息是否准确。
1.统计信息概述
(1).存储引擎与统计信息
Memory引擎根本不存储索引统计信息。
MyISAM将索引统计信息存储在磁盘中,ANALYZE TABLE需要进行一次全索引扫描来计算索引基数。在整个过程中需要锁表。
直到MySQL5.5版本,InnoDB也不在磁盘存储索引统计信息,而是通过随机的索引访问进行评估并将其存储在内存中。
(2).统计信息更新时机
InnoDB会在表首次打开,或者执行ANALYZE TABLE,抑或表的大小发生了非常大的变化(大小变化超过了1/16或者新插入20亿行都会触发)的时候计算索引的统计信息。
InnoDB在打开某些INFORMATION_SCHEMA表、或者使用SHOW TABLE STATUS和SHOW INDEX,抑或在MySQL客户端开启自动补全功能的时候都会触发统计信息的更新。这往往会打来系统开销的增大。针对SHOWINDEX查看统计信息,就一定会触发统计信息的更新,可以关闭innodb_stats_on_metadata参数来避免问题。
(3).稳定统计信息
如果想要稳定的执行计划,并在系统重启后更快地生成这些统计信息,那么可以使用系统表来持久化这些索引统计信息,甚至还可以在不同的机器间迁移索引统计信息,这样新环境就不须收集这些数据了。在Percona5.1版本和官方5.6的版本都加入了这个特性。在Percona版本是通过innodb_use_sys_stats_table参数可以启用这个特性。在官方5.6版本中可以通过innodb_analyze_is_persistent参数控制。
(4).统计信息与执行计划
计算依据
这个根据一系列的统计信息得来的,包括:每个表或者索引的页面个数、索引的基数、索引和数据行的长度、索引分布情况。优化器在评估时不考虑任何层面的缓存,它假设任何数据都需要一次磁盘I/O。
导致错误执行计划的原因
统计信息不准确
有的存储引擎提供的信息是准确的,有的偏差很大。例如InnoDB因为其MVCC的架构,并不能维护一个数据表行数的精确统计信息。
查询优化器与统计信息
在服务器层有查询优化器,却没有保存数据和索引的统计信息。统计信息是由存储引擎实现,不同的存储引擎处理不同。有的存储引擎(例如Archive引擎),则根本没有统计信息。当优化器需要的时候,则向存储引擎获取相应的统计信息。
2.查看统计信息
(1).SHOW命令
SHOW TABLE STATUS
查看表的统计信息
SHOW INDEX SHOW KEYS
查看索引的统计信息
(2).数据字典表
在5.6的版本中,InnoDB的统计信息是可以持久化的。对应的数据字典为innodb_table_stats和innodb_index_stats。
mysql> select * from innodb_table_stats where database_name='test'and table_name='t_big';
mysql> select * from innodb_index_stats wheredatabase_name='test' and table_name='t_big';
(3).统计信息说明
SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']
Name: 表名
Engine: 表的存储引擎类型(ISAM、MyISAM或InnoDB)
Row_format: 行存储格式(Fixed-固定的、Dynamic-动态的或Compressed-压缩的)
Rows: 行数量。
Avg_row_length: 平均行长度。
Data_length: 数据文件的长度。
Max_data_length: 数据文件的最大长度。
Index_length: 索引文件的长度。
Data_free: 已分配但未使用了字节数。
Auto_increment: 下一个autoincrement(自动加1)值。
Create_time: 表被创造的时间。
Update_time: 数据文件最后更新的时间。
Check_time: 最后对表运行一个检查的时间。执行mysqlcheck命令后更新,仅对MyISAM有效。
Create_options: 额外留给CREATE TABLE的选项。
Comment: 当创造表时,使用的注释。
Version: 数据表的'.frm'文件版本号。
Collation: 表的字符集和校正字符集(在中MySQL4.1.1新增的)。
Checksum: 实时的校验和值(如果有的话)
SHOW INDEX FROM tbl_name [FROM db_name]
Table: 表名
Non_unique: 0,如果索引不能包含重复。
Key_name: 索引名
Seq_in_index: 索引中的列顺序号,从1开始。
Column_name: 列名。
Collation: 列怎样在索引中被排序。在MySQL中,这可以有值A(升序)或NULL(不排序)。
Cardinality: 索引中唯一值的数量。
Sub_part: 如果列只是部分被索引,索引字符的数量。
Packed: 表示键值是如何压缩的,NULL表示没有压缩。
Null: 当字段包括NULL的记录是YES,它的值为,反之则是''。
Index_type: 使用了哪种索引算法(有BTREE、FULLTEXT、HASH、RTREE)。
Comment: 各种不同的备注。
3.收集统计信息
(1).收集方式
自动
收参数innodb_stats_auto_recalc的控制,默认是ON。触发条件是设置了持久化(包括全局变量或单个表设置),且数据变化超过10%,就会触发收集统计信息。收集采样页数量仍然受参数innodb_stats_persistent_sample_pages来指定。
手动
ANALYZE TABLE table_name;
(2).样本页数量(InnoDB)
InnoDB通过抽样的方式来计算统计信息,首先随机地读取少量的索引页面,然后以此为样本计算索引的统计信息。在老的InnoDB版本中,样本页面数为8。新版本的InnoDB可以通过参数来设置样本页的数量。设置更大的值,理论上来说可以帮助生成更准确的统计信息,特别是对于某些超大的数据表来说。
4.修改统计信息
可以修改innodb_table_stats、innodb_index_stats,实现修改统计信息。但需要注意的是,修改完毕后还需要使用"FLUSHTABLE tbl_name"来使MySQL重新加载更新后的统计信息。