-
在一次查询中,MySQL只能使用一个索引。
-
在真实项目中,SQL语句中的WHERE子句里通常会包含多个查询条件还会有排序、分组等。
-
若表中索引过多,会影响INSERT及UPDATE性能,简单说就是会影响数据写入性能。因为更新数据的同时,也要同时更新索引。
-
最实际的好处当然是查询速度快,性能好。
举例:
创建一张数据表
CREATE TABLE `student` ( `studentId` int(11) NOT NULL, `studentName` varchar(255) DEFAULT NULL, `gradeId` int(11) DEFAULT NULL, `schoolId` int(11) DEFAULT NULL, PRIMARY KEY (`studentId`), KEY `s_g_s` (`schoolId`,`gradeId`,`studentId`) )
假设每个班有50名学生,一个年级有10个班,一所学校有4个年级,共有3所学校,那么总共会有6000名学生
若要查询出第2所学校3年级学生的姓名,SQL如下SELECT studentName FROM student WHERE schoolId=2 AND gradeId=3
如果使用名为s_g_s
的联合索引,那通过索引,MySQL可筛选掉大部分不满足查询条件的学生信息,在这个例子中,可筛掉5500条记录,这样MySQL只需回表查询剩余的500条记录即可得到结果。
如果只使用schoolId上的单列索引,只能筛掉4000条记录,需回表扫描过滤剩余的2000条记录才能得到结果,从数量上看差了一个数量级。性能自然不佳。
若要查询出第2所学校3年级学生的姓名并按照studentId倒排,SQL如下SELECT studentName FROM student WHERE schoolId=2 AND gradeId=3 ORDER BY studentId DESC
这条SQL若没有多列索引,在较大数据量下性能会很差。但有了s_g_s
索引,排序可以在索引上直接完成,不用MySQL取回记录后,再在内存或者磁盘上进行一次排序。性能提升很大。
若要查询出第2所学校3年级学生的studentId,SQL如下SELECT studentId FROM student WHERE schoolId=2 AND gradeId=3
对于这条查询,s_g_s
索引包含所有需要查询的字段的值,MySQL根本不需要再去读取表中的记录,直接全部在索引上完成,这是性能最高的一种索引,通常称为“覆盖索引”。
这个例子有点“简陋”,但还是可以说明一些问题。
综上,在实际项目中,
- 联合索引的使用要远多于单列索引。
- 联合索引使用正确对性能提升很有帮助。
- 怎么加索引,把哪些列加索引,加几个索引都是需要根据项目中使用到的SQL及数据表中数据的分布、数据的区分度去衡量的。
- 使用MySQL explain工具来解析SQL查询执行计划。