索引

InnoDB和MyISAM都支持B-tree索引,可以支持快速的相等查询(例如id = 1)和范围查询(例如>、

B-tree

索引使用

explain可以查看MySQL对一个语句的执行计划,其中的key是查询使用的索引。

MySQL查询的时候只会对每个表用一个索引,而且只用这个索引的最左前缀。

例如对一个三个字段组成的组合索引Comb(CountryCode, District, Population)

MySQL可以用下面这3个部分:

只用CountryCode部分

只用CountryCode + District部分

用CountryCode + District + Population全部

组合索引中各部分的顺序也会影响查询,最好是先比较相等的字段,再到范围字段。

先比较相等,再做范围查询,减少扫描行数

查询计划中可以根据key_len或JSON格式的查询计划中used_key_parts来判断用了索引的那个部分。

覆盖索引就是覆盖了一个查询中Select、Where、Group by、Order by出现的全部字段的索引。

查询

Group by优化

没有索引的情况下要扫描整个表,还会用临时表存放结果。

筛选条件是相等比较时,用包含筛选条件和Group by字段的组合索引(或覆盖索引),可以避免临时表。(效果类似上面的图,先通过筛选条件的索引找到Group的索引,根据Group的索引知道Group的个数和数据的位置,然后对每个Group扫描就可以了)。

如果筛选条件是范围查询,可以已通过union改成多个查询合并,来减少临时表的大小(每个查询不用临时表,但最后合并要)。

在对一个表进行Group by,Group by条件只包含索引的最左前缀,而且只用max/min对这个索引的前缀进行聚合运算,MySQL可以进行松散的索引扫描,只用扫描少部分的索引,很快。(应该是索引里直接保存了max/min的结果来减少对一课子树的扫描)。

Order by优化

Order by查询数据多的时候要进行文件排序,而索引是已经排序的,可以避免文件排序,Limit条数较少也可以避免文件排序。

计算表达式

如果查询条件里有函数,MySQL是不能用函数参数上的索引快速筛选的,这时通常要用单独的一列保存函数调用的结果,但是要在应用层或触发器保证正确更新。MySQL 5.7有了虚拟/生成字段,可以直接在一个虚拟字段里保存函数调用的结果,虚拟字段不会被保存,但是可以建索引!