理解索引的基数
2014-06-13 22:20 游乐场123 阅读(2065) 评论(0) 编辑 收藏 举报当一个查询中使用不止一个索引的时候,MySQL会试图找到一个最高效的索引。它通过分析每条索引内部数据分布的统计信息来做到这一点。本例中我们要查询创建于1980年的所有品牌,因此我们在artist表的type列上创建一个索引,因为我们要在其上执行搜索。
mysql> ALTER TABLE artist ADD INDEX (type);
为了在所有MySQL 5.x版本中更好地说明这一点,在本例中我们要禁用一个优化器设置:
mysql> SET @@session.optimizer_switch='index_merge
intersection=off';
mysql> EXPLAIN SELECT artist_id, name, country_id
-> FROM artist
-> WHERE type='Band'
-> AND founded = 1980\G
********************* 1. row ***********************
id: 1
select_type: SIMPLE
table: artist
type: ref
possible_keys: founded,founded_2,type
key: founded
key_len: 2
ref: const
rows: 1216
Extra: Using where
本例中,MySQL必须在possible_keys列出的索引中做出选择。优化器会根据最少工作量的估算开销来选择索引,这往往和人们想到的选择顺序不一样。我们可以使用索引基数来确定最有可能被选中的索引。请看下面的示例:
mysql> SHOW INDEXES FROM artist\G...
********************* 3. row ***********************
Table: artist
Non_unique: 1
Key_name: founded
Seq_in_index: 1
Column_name: founded
Collation: A
Cardinality: 846
...
********************* 5. row ***********************
Table: artist
Non_unique: 1
Key_name: type
Seq_in_index: 1
Column_name: type
Collation: A
Cardinality: 10
...
这些信息表明founded列拥有更高的基数,也就是说该列中唯一值的数量越多,那么越有可能在选用这个索引时以更少的读操作中找到需要的记录。这些统计信息只是估计值。从数据分析中我们可以知道,artist表中type只有4个唯一值,但在统计信息中则不是这样。
关于基数不得不提的一点就是选择性。仅仅知道索引中唯一值的数目意义并不大,重要的是将这个数值和索引中的总行数做比较。选择性就是表中明确值的数量和表中包含的记录的总数的关系。理想情况下,选择性值为1,且每一个值都是一个非空唯一值。一个有着优秀选择性的索引意味着有更少的相同值的行。当某一列中仅仅有少数不同的值的时候就会有较差的选择性——例如性别或者状态列。当查询需要用到所有列时,这些信息不但可以帮助我们判断索引是否高效,还可以告诉我们如何在多列索引中对列进行排序。
结果中显示的索引基数提供了一些简单的线索。下面的两个查询想要查找20世纪80年代的乐队和组合。
mysql> EXPLAIN SELECT artist_id, name, country_id
-> FROM artist
-> WHERE founded BETWEEN 1980 AND 1989 AND
type='Band'\G
********************* 1. row ***********************
...
possible keys: founded,founded_2,type
key: founded
key_len: 2
ref: NULL
rows: 18690
Extra: Using where
mysql> EXPLAIN SELECT artist_id, name, country_id
-> FROM artist
-> WHERE founded BETWEEN 1980 AND 1989 AND
type='Combination'\G
********************* 1. row ***********************
..
possible keys: founded,founded_2,type
key: type
key_len: 1
ref: const
rows: 19414
Extra: Using where
这两个查询看起来很简单,但它们却根据列信息分布的详细统计信息选择了不同的索引路径。