四、优化文件排序
如果MySQL发现sort_buufer内存太小,会影响排序效率,才会采用rowid排序算法,使用rowid算法的好处就是sort_buffer中可以一次排序更多的行,缺点就是需要回表。
在MySQL中如果内存够用,就多利用内存,尽量减少磁盘访问。所有rowid的算法不会被优先选择,因为回表会造成过的磁盘读。
不是所有的order by语句,都需要排序操作的,上面分析的两种排序算法的由来都是因为原来的数据都是无序的。
问题:什么是有序的?
看过了索引那一期文章后,你现在应该知道以下两点。
索引本身具有顺序性,在进行范围查询时,获取的数据已经排好了序,从而避免服务器再次排序和建立临时表的问题。
索引的底层实现本身具有顺序性,通过磁盘预读使得在磁盘上对数据的访问大致呈顺序的寻址,也就是将随机的I/O变为顺序I/O。
问题:如何防止进行排序
现在你应该知道答案了,就是给需要排序的列创建联合索引。
现在给phone、code建立一个联合索引,对应的SQL语句如下
alter table evt_sms add index idx_phone_code (phone,code);
那么执行同样的语句就不会使用排序操作了,接下来看一下执行流程
执行流程
1、从索引(phone,code)找到满足phone='123456’的记录,取出phone、code的值,作为结果集的一部分直接返回
3、从索引(phone、code)取下一个记录,同样取出phone、code的值,作为结果集的一部分直接返回
4、重复步骤2直到查出1000行数据,或者不满足查询条件为止
五、总结
order by没有用到索引时,执行计划中会出现using filesort
using filesort根据参数sort_buffer_size的值来决定使用需要使用临时文件
max_length_for_sort_data参数决定是否使用rowid算法,若放入sort_buffer的每行数据大于设置的值就会使用rowid算法
现在你应该知道了rowid排序只是把需要排序的字段和主键ID放入sort_buffer中,而文件排序则是把查询的所有字段全部放入sort_buffer中。
还有rowid会多造成一次回表操作,这个你也要知道。
最后提到了优化order by语句,这里提到了建立覆盖索引,利用索引的有序性直接返回结果不用进行排序。
这里并不是提倡大家在实际生产环境中盲目建立,而是根据具体业务情况,如果数据非常的小在内存排序是非常快的。并且覆盖索引会占用更多的存储空间和维护开销。