索引可以包含一个或多个列的值。如果索引包含多个列,那么列的顺序也十分重要,因为MySQL只能高效的使用索引的最左前缀列。
索引类型
在MySQl中,索引是在存储引擎层而不是服务层实现的
B-Tree索引

页节点比较特别,它们的指针指向的是被索引的数据,而不是其他的节点页(不同引擎的“指针”类型不同)。
假设有如下数据表:
create table people(
last_name varchar(50) not null,
first_name varchar(50) not null,
dob date not null,
gender enum('m','f') not null,
key(last_name,first_name,dob)
);

使用场景
B-Tree索引适用于全键值、键值范围或键前缀查找。其中键前缀查找只适用于根据最左前缀的查找。
有如下的查询类型:
-
全值匹配:全值匹配指的是和索引中的所有列进行匹配
-
匹配最左前缀:只使用索引的前几列
-
匹配列前缀:只匹配某一列的值的开头部分。例如前面提到的索引可用于查找所有以J开头的姓的人。这里也只使用了索引的第一列
-
匹配范围值: 例如前面提到的索引可用于查找姓在Allen和Barrymore之间的人。这里也只使用了索引的第一列
-
精确匹配某一列兵范围匹配另外一列:前面提到的索引也可用于查找所有姓为Allen,并且名字是字母K开头(比如Kim、Karl等)的人。即第一列last_name全匹配,第二列first_name范围匹配
-
只访问索引的查询:B-Tree通常可以支持“只访问索引的查询”,即查询只需要访问索引,而无需访问数据行。(这种成为索引覆盖)
因为索引书中的节点是有序的,所以除了按值查找之外,索引还可以用于查询中的ORDER BY操作。可以在创建索引的时候,在列名后面指定排序顺序。
限制
- 如果不是安装索引的最左列开始查找,则无法使用索引。例如之前的例子中,无法用与查找名字为Bill的人,也无法查找某个特定生日的人
- 不能跳过索引中的某个列。例如不能查找姓为Smith并且某个特定日期出生的人
- 如果查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找。例如 有查询 where last_name='smith' and first_name like 'J%' AND dob='1976-12-23',这个查询只能使用索引的前两列,因这里like是一个范围条件。如果范围查询劣质的数量有限,那么可以通过使用多个等于条件来代替范围条件。
哈希索引
哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码。哈希索引将所有的哈希码存储在索引中,同时在哈希表中表村指向每个数据行的指针。
在MySQL中,只有Memory引擎显示支持哈希索引。
空间数据索引(R-Tree)
MyISAM表支持空间索引,可以用作地理数据存储。和B-Tree索引不同,这类索引无需前缀查询。空间索引会从所有维度来索引数据。
全文索引
是一种特殊类型的索引,它查找的是文本中的关键词,而不是直接比较索引中的值。
索引策略(索引的正确使用姿势)
正确创建和使用索引是实现高性能查询的基础
独立的列
如果查询中的列不是独立的,则MySQL不会使用索引。独立的列是指索引不能是表达式的一部分,也不能是函数的参数。 例如,下面这个无法使用actor_id列的索引
select actor_id from sakila.actor where actor_id+1=5;
另一个常见的错误:
select ... where TO_DAYS(CURRENT_DATE) - TO_DAYS(date_col) <=10;