暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL之order by的使用(中)

ITwords 2021-08-26
204

公众号后台回复“学习+JavaSE”,即可免费获得学习资料





前言:本公众号将推出系列性的知识分享,以专题或者模块的方式,向读者分享学习体会和心得。所以想要学习的朋友可以点击关注,一起学习。



除夕快乐


昨天的排序算法中,大家会发现只对原表中的数据读了一遍,剩下的都是在sort_buffer和临时文件中实现的。这个算法有个问题就是,如果要返回的查询字段很多的时候,sort_buffer里面要放的字段太多,这样内存 中可以同时放下的行数就会变少,要分成很多的临时文件,排序性能也可能会变差。

所以单行数据量很大的,执行效率会很不理想。

所以需要修改一个参数来使用MySQL的另外一个算法:

    SET max_length_for_sort_data = 16;

    max_length_for_sort_data,是mysql中专门用来排序行数长度的一个参数,他的意思是如果一行的长度超过这个值的话,就会换一个算法。

    而在昨天的介绍的查询的是字段有age、name、city的大小是36,修改以后,我们看看会有什么变化?

    新的算法放入sort_buffer的内容只有:需要排序的字段(name)和id。

    但是我们需要查询的是三个字段,所以age和city就不能直接返回了,所以查询的过程变成了如下的模样:

    1. 初始化sort_buffer,确定放入两个字段,即name和id;

    2. 从索引city找到第一个满足city='杭州’条件的主键id,也就是图中的ID_X;

    3. 到主键id索引取出整行,取name、id这两个字段,存入sort_buffer中;

    4. 从索引city取下一个记录的主键id;

    5. 重复步骤3、4直到不满足city='杭州’条件为止,也就是图中的ID_Y;

    6. 对sort_buffer中的数据按照字段name进行排序;

    7. 遍历排序结果,取前1000行,并按照id的值回到原表中取出city、name和age三个字段返回给客户端。

    执行的流程图如下:

    对比昨天的全字段排序,会发现,rowid排序的时候,会比昨天的排序多访问了一次表user的主键索引,就是步骤7。

    需要说明的是,最后的“结果集”是一个逻辑概念,实际上MySQL服务端从排序后的sort_buffer中依次取出id,然后到原表查到city、name和age这三个字段的结果,不需要在服务端再耗费内存存储结果,是直接返回给客户端的。

    根据这个说明过程和图示,你可以想一下,这个时候执行select @b-@a,结果会是多少呢?

    现在,我们就来看看结果有什么不同。

    首先,图中的examined_rows的值还是4000,表示用于排序的数据是4000行。但是select @b-@a这个语句的值变成5000了。

    因为这时候除了排序过程外,在排序完成后,还要根据id去原表取值。由于语句是limit 1000,因此会多读1000行。

    从OPTIMIZER_TRACE的结果中,你还能看到另外两个信息也变了。

    • sort_mode变成了<sort_key, rowid>,表示参与排序的只有name和id这两个字段。

    • number_of_tmp_files变成10了,是因为这时候参与排序的行数虽然仍然是4000行,但是每一行都变小了,因此需要排序的总数据量就变小了,需要的临时文件也相应地变少了。


    好了,今天的介绍到这里就结束了,大家有问题了可以私信我,大家共同学习,一起进步哈!


    喜欢的同学可以点击“在看”,并且关注ITwords微信公众号,第一时间获取更新内容。您的转发和点赞将是我原创的动力,感谢您的支持。


    扫描二维码

    获取更多精彩

    ITwords



    尾言:下一篇MySQL之order by的使用(下)


    往期回顾:

    MySQL之order by的使用(上)

    文章转载自ITwords,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论