关键词:索引分布 cardinality
语法:ANALYZE TABLE 表名;
作用:执行ANALYZE TABLE,MySQL会分析指定表的键的值(主键、唯一键、外键等,也可以看成就是索引列的值)分布情况,并会记录分布情况。
限制:执行此语句需要具有SELECT、DELETE权限,且只对存储引擎为InnoDB、MyISAM、NDB的表有作用,不能用于视图。如下图所示,actor_info是视图,执行失败:
执行输出结果:
列 |
解释 |
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 表名
ANALYZE TABLE分析后的统计结果会反应到cardinality的值,该值统计了表中某一键所在的列,不重复的值的个数。该值越接近表中的总行数,则在表连接查询或者索引查询时,就越优先被优化器选择使用。也就是索引列的cardinality的值与表中数据的总条数差距越大,即使查询的时候使用了该索引作为查询条件,实际存储引擎实际查询的时候使用的概率就越小。我们都知道,索引尽量建立在重复值很少的列上就是基于这个原因。下面通过例子来验证下。cardinality可以通过SHOW INDEX FROM 表名查看:
film表中的数据总条数是1000,由上图可知,film表建立了四个索引,前两个的索引的cardinality就等于表的数据总条数,表示很优秀。下面两个的值才是1,就很差了。查看select * from film where film_id = 1;的执行计划,其中film_id是索引列,cardinality=1000:
从执行计划的结果可以看出,上面的语句是使用了索引的。再来查看select * from film where language_id = 1;的执行计划,其中language_id也是索引列,但是cardinality=1:
由上面执行计划的结果可以看出,虽然语句中使用了索引,但是存储引擎在实际执行查询的时候并没有使用索引。因为cardinality的值与表中的数据总条数差距太大了。