单列索引: 只有一个字段的索引

组合索引(复合索引): 两个或两个以上字段组成的索引. 组合索引遵循左侧原则, 也就是一个查询可以只使用组合索引最左侧的一部分.

例子:

创建  Index(a, b,  c) 组合索引 ,相当于创建了(a)单列索引、(a, b)联合索引以及(a, b, c)联合索引。当where中的顺序只有是这三个顺序时,  才能使用索引。

1. 组合索引查询

查询( 索引 Index(a, b,  c) )

是否可以

a>5


a=5  and b>6


a=5 and b=6 and c=7


b=6 and a=5 and c=7

√ mysql会自动优化为a=5 and b=6 and c=7

a=5 and b=6 and c in (2, 3)


b>5

× 查询条件不包括组合索引首列字段

b=6 and c>7

× 查询条件不包括组合索引首列字段

2. 范围查询 (部分组合索引查询)

查询( 索引  Index(a, b, c) )

 

a>5 and b=2

√  当范围查询使用第一列,查询条件仅能使用第一列

a=5 and b>6 and c=2

√ 当范围查询使用第二列,查询条件仅能使用前两列

a=5 and b in(2,3) and c=3

√ 当范围查询使用第二列,查询条件仅能使用前两列

3. 组合索引排序

排序(索引 Index(a,b))

 

order by a

首列排序

a=5 order by b

√ 第一列过滤后,第二列排序

order by a desc, b desc

√ 注意,此时两列以相同的顺序排列

a>5 order by a

√ 数据检索和排序均在第一列

order by b

× 排序在索引的第二列

a>5 order by b

× 范围查询在第一列,排序在第二列

a in (2,3) order by b

× 范围查询在第一列,排序在第二列

order by a asc ,b desc

× 此时两列以不同的顺序排序

4. 实例

查出满足以下条件的学生id:
mysql>select  id  from student where name ='Liu'  and score=90 and  age=26;
因为我们不想扫描整表,故考虑用索引。

1. 单列索引:
alter table student add index name (name);
name列建索引,这样就把范围限制在name='Liu'的结果集1上,之后扫描结果集1,产生满足score=90 的结果集2,再扫描结果集2,找到 age=26的结果集3,即最终结果。

由于建立了name列的索引,与执行表的完全扫描相比,效率提高了很多,但我们要求扫描的记录数量仍旧远远超过了实际所需 要的。虽然我们可以删除name列上的索引,再创建fname或者age 列的索引,但是,不论在哪个列上创建索引搜索效率仍旧相似。

2. 多列索引:
alter table student add index name_score_age (name, score, age);
为了提高搜索效率,我们需要考虑运用多列索引,由于索引文件以B-Tree格式保存,所以我们不用扫描任何记录,即可得到最终结果。

注:在mysql中执行查询时,只能使用一个索引,如果我们在lname,fname,age上分别建索引,执行查询时,只能使用一个索引,mysql会选择一个最严格(获得结果集记录数最少)的索引。

3. 上例中我们创建了name_score_age多列索引,相当于创建了(name)单列索引,(name, score)组合索引以及(name, score, age)组合索引。

注:在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。