MySQL之ANALYZE TABLE

时间:2024-05-20 17:52:14

关键词:索引分布    cardinality

 


语法:ANALYZE TABLE 表名;

作用:执行ANALYZE TABLE,MySQL会分析指定表的键的值(主键、唯一键、外键等,也可以看成就是索引列的值)分布情况,并会记录分布情况。

限制:执行此语句需要具有SELECT、DELETE权限,且只对存储引擎为InnoDB、MyISAM、NDB的表有作用,不能用于视图。如下图所示,actor_info是视图,执行失败:

MySQL之ANALYZE TABLE

执行输出结果:

解释

Table

表名

Op

总是analyze

Msg_type

status, error, info, note, 或者 warning

Msg_text

信息


在对表的键分布进行分析时,ANALYZE TABLE操作会将指定的表从表定义缓存中移除,并且会对于InnoDB、MyISAM表会加上读锁,即其他会话只能对表数据进行查询,无法对表数据进行修改,直到执行分析的会话释放了锁。

默认的,MySQL服务会将 ANALYZE TABLE语句写到binlog中,以便在主从架构中,从服务能够同步数据。(从服务通过binlog与主服务完成数据同步)。可以添加参数取消将语句写到binlog中:

ANALYZE NO_WRITE_TO_BINLOG TABLE 表名 或者 ANALYZE LOCAL TABLE 表名

MySQL之ANALYZE TABLE


ANALYZE TABLE分析后的统计结果会反应到cardinality的值,该值统计了表中某一键所在的列,不重复的值的个数。该值越接近表中的总行数,则在表连接查询或者索引查询时,就越优先被优化器选择使用。也就是索引列的cardinality的值与表中数据的总条数差距越大,即使查询的时候使用了该索引作为查询条件,实际存储引擎实际查询的时候使用的概率就越小。我们都知道,索引尽量建立在重复值很少的列上就是基于这个原因。下面通过例子来验证下。cardinality可以通过SHOW INDEX FROM 表名查看:

MySQL之ANALYZE TABLE

film表中的数据总条数是1000,由上图可知,film表建立了四个索引,前两个的索引的cardinality就等于表的数据总条数,表示很优秀。下面两个的值才是1,就很差了。查看select * from film where film_id = 1;的执行计划,其中film_id是索引列,cardinality=1000:

MySQL之ANALYZE TABLE

从执行计划的结果可以看出,上面的语句是使用了索引的。再来查看select * from film where language_id = 1;的执行计划,其中language_id也是索引列,但是cardinality=1:

MySQL之ANALYZE TABLE

由上面执行计划的结果可以看出,虽然语句中使用了索引,但是存储引擎在实际执行查询的时候并没有使用索引。因为cardinality的值与表中的数据总条数差距太大了。