排序与索引
MySQL有两种方式可以生成有序的结果:通过排序操作;或者按索引顺序扫描。
只有当索引的列顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向(倒序或正序)都一样时,MySQL才能够使用索引来对结果做排序。
如果查询需要关联多张表,则只有当ORDER BY子句引用的字段全部为第一个表时,才能使用索引做排序。ORDER BY子句和查找型查询的限制是一样的:需要满足索引的最左前缀的要求;否则,MySQL都需要执行排序操作,而无法利用索引排序。
有一种情况下ORDER BY子句可以不满足索引的最左前缀的要求,就是前导列为常量的时候。如果WHERE子句或者JOIN子句中对这些列指定了常量,就可以“弥补”索引的不足。
一些创建索引的技巧
假设有组合索引(sex,country),如果碰到where语句中不需要包含sex,为了让组合索引生效则可以在where语句中加上 AND SEX IN('m','f')来让MySQL选择该索引。这样写并不会过滤任何行,和没有这个条件时返回的结果相同。但是必须加上这个列的条件,MySQL才能够匹配索引的最左前缀。
尽可能将需要做范围查询的列放到索引的后面,以便优化器能使用尽可能多的索引列。
SELECT actor_id FROM sakila.actor
-> WHERE actor_id > 45\G
SELECT actor_id FROM sakila.actor
-> WHERE actor_id IN(1, 4, 99)\G
第一个查询是范围查询,对于范围条件查询,MySQL无法再使用范围列后面的其他索引列了。
第二个查询(in ...))就是**多个等值条件查询。**对于“多个等值条件查询”则没有这个限制。
减少索引和数据的碎片
有三种类型的数据碎片:
行碎片(Row fragmentation)
行间碎片(Intra-row fragmentation)
剩余空间碎片(Free space fragmentation)
可以通过执行OPTIMIZE TABLE或者导出再导入的方式来重新整理数据。这对多数存储引擎都是有效的。