事先已经有两张表:course(100条记录),student_info(1000000条记录)
1、字段的数值有唯一性限制
索引自身可以有约束的作用,例如唯一索引、主键索引都可以起到唯一性约束,在数据表中如果某个字段是唯一性的,就可以直接创建唯一性索引或者主键索引,这样可以更快地通过这个索引来确定某条记录。
2、频繁作为WHERE查询条件的字段
在数据量大的情况下某个字段在SELECT语句的WHERE条件中经常被使用到,那么就需要给该字段创建索引,创建普通索引就可以大幅提升数据查询速率。
(1)先没有给student_id字段添加索引
sql
SELECT course_id,class_id,name,create_time,student_id
FROM student_info
WHERE student_id = 123110; # 0.293s
(2)给student_id字段添加索引
sql
SELECT course_id,class_id,name,create_time,student_id
FROM student_info
WHERE student_id = 123110; # 0.029s
3、经常GROUP BY和ORDER BY的列
索引就是为了让数据按照某种顺序进行存储或检索,当使用GROUP BY对数据进行分组或者使用ORDER BY对数据进行排序时,就需要对分组或者排序的字段进行索引。对于多个列的时候,也可以使用组合索引(联合索引)。
(1)student_id字段没有索引
sql
SELECT student_id,COUNT(*) AS num
FROM student_info
GROUP BY student_id
LIMIT 100; # 2.320s
(2)给student_id字段添加索引
sql
SELECT student_id,COUNT(*) AS num
FROM student_info
GROUP BY student_id
LIMIT 100; # 0.026s
如果GROUP BY的字段是student_id,ORDER BY的字段是create_time。此时适合创建联合索引,并且按照(student_id,create_time)这个联合索引顺序的效率最高。
4、UPDATE、DELETE的WHERE条件列
对数据按照某个条件进行查询后再进行UPDATE或DELETE的操作,如果对WHERE字段创建了索引,就能大幅提升效率。原理:需要先根据WHERE条件列检索出来这条记录,然后在对他进行更新或删除。如果进行更新的时候,更新的字段是非索引字段,提升的效率会更明显,这是因为非索引字段更新不需要对索引进行维护。
5、DISTINCT字段需要创建索引
创建索引后能看到SQL查询效率有了提升,同时显示的student_id还是按照递增的顺序进行展示的。这是因为索引会对数据按照某种顺序进行排序。
(1)student_id字段没有索引
sql
SELECT DISTINCT(student_id)
FROM student_info; #1.157s
(2)给student_id字段添加索引
sql
SELECT DISTINCT(student_id)
FROM student_info; #0.598s
6、多表JOIN连接操作时,创建索引注意事项
①连接表的数量不超过三张,因为每增加一张表就相当于增加了一次嵌套的循环,数量级的增长会很快,对查询效率很不友好;
②对WHERE条件创建索引,因为WHERE才是对数据条件的筛选,这一点在数据量很大的情况下尤为可观;
③对用于连接的字段创建索引,并且该字段在多张表中的类型必须一致。
(1)name字段没有索引
sql
SELECT student_info.course_id, name, student_info.student_id, course_name
FROM student_info JOIN course
ON student_info.course_id = course.course_id
WHERE name = '462eed7ac6e791292a79'; #0.215s
(2)name字段增加了索引
sql
SELECT student_info.course_id, name, student_info.student_id, course_name
FROM student_info JOIN course
ON student_info.course_id = course.course_id
WHERE name = '462eed7ac6e791292a79'; #0.024s
7、使用列的类型小的创建索引
类型小指的就是该类型所表示的数据范围大小,例如TINYINT<MEDIUMINT<INT<BIGINT。
在能满足数据表示的前提之下应当选择较小的类型,这是因为:
- 数据类型越小,查询时的比较操作就越快;
- 数据类型越小,索引占用的存储空间就越小,一个数据页可以放下更多的记录,从而可以减少磁盘的I/O,加快读写效率。
这个规则对于主键更加适配,我们知道无论是聚簇索引还是二级索引都会记录主键值,如果主键使用更小的数据类型,就意味着节省更多的存储空间以及更高效的I/O。
8、使用字符串前缀创建索引
如果要对字符串建立索引,而且这个字符串还很长就会有以下问题:
- B+树索引中的记录要把完整的字符串存储起来,更加费时。并且字符串越长在索引中占用的存储空间就越大;
- 如果B+树索引中索引列存储的字符串很长,在做比较的时候也会花很长时间。
基于此我们可以建立前缀索引,截取字段前面一部分内容建立索引。根据前缀相同的记录的主键值回表查询完整的字符串值。在阿里的规定中就强制要求了:在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引的长度。
sql
# 索引长度计算公式---越接近1越好----一般来说长为20的索引
count(distinct left(列名, 索引长度))/count(*)
9、散列性高的列适合作为索引
列的基数是说经过distinct之后的记录数,在记录行数一定的情况下,列的基数越大,该列中的值越分散;列的基数越小,该列中的值越集中。对列的基数大的列建立索引效果比较好。
sql
select count(distinct a)/count(*)
from table;
在联合索引中将区分度高的列放在前面效果好。
10、使用最频繁的列放到联合索引的左侧
由于"最左前缀原则",使用多的列放到左边会增加联合索引的使用率。
11、在多个字段都要创建索引的情况下,联合索引优于单值索引
上面第三条的GROUP BY 和 ORDER BY的例子也可以说明这一点。
索引虽好,但不要过量创建。