zoukankan      html  css  js  c++  java
  • mysql的sort by学习

    前沿

    学习了mysql的next-key-lock后,现在正式进入sort by的学习阶段。有时在项目里会用到sort by语句。我也听说sort by有可能会对mysql造成压力,所以要学习一下sort by的过程,从而才能深刻的了解自己的sort by语句对mysql的压力,避免线上性能低下或者事故。

    场景 

    有这么一个场景,要对杭州市民按照姓名排序,取前1000个人。

    给city加索引,表设计如下:

    1 CREATE TABLE `t` ( `id` int(11) NOT NULL, 
    2 `city` varchar(16) NOT NULL, 
    3 `name` varchar(16) NOT NULL, 
    4 `age` int(11) NOT NULL, 
    5 `addr` varchar(128) DEFAULT NULL, 
    6 PRIMARY KEY (`id`), 
    7 KEY `city` (`city`)) ENGINE=InnoDB;

    然后执行:

    1 select city,name,age from t where city='杭州' order by name limit 1000 ;

    全字段排序

    那接下来引擎层是如何执行的呢?大致过程如下:

    1、初始化该sql线程的sort buffer,其大小是sort buffer size决定的。

    2、city索引上查找第一个city='杭州'的记录,取出id

    3、到主键索引取出select所需的三个字段:city、name和age,插入到sort buffer中;

    4、然后继续在city索引上查找下一个记录,重复2、3步,直到city不等于'杭州';

    5、在sort buffer中按照name进行排序

    6、取出前1000的记录,返回给用户

    这边有一个问题,就是如果数据量太大,那么sort buffer不一定能放下。那此时就要借助磁盘辅助排序。mysql在这边做了优化,是将数据放到若干个小的临时文件中,先各自排序,然后合并成一个大的临时文件,应该是类似于归并排序吧。

    上述排序的好处是读完原表中数据后只需借助sort buffer和临时文件排序就行了。

    row id排序

    还有一个问题,就是要返回的当行数据过大时,会导致sort buffer中放不了多少行数据,就不得不借助临时文件排序,影响性能。row id排序可以缓解这种情况。通过如下配置,告知mysql单行超过多大需要使用row id排序。

    假设city, name, age三个字段有32字节,而我们设置超过16个字节就采用row id排序。

    1 SET max_length_for_sort_data = 16;

    row id排序过程大致如下:

    1、初始化sort buffer,确定放入两个字段:name和id;

    2、从索引 city 找到第一个满足 city='杭州’条件的主键 id

    3、用主键id在主键索引中查找name字段

    4、将id和name放入sort buffer中

    5、索引中继续查找下一个满足条件的主键id,重复3、4步骤,直到遇到第一个不满足条件的记录。

    6、在sort buffer中按name排序,取前1000个

    7、回表,获取这1000个id对应的city和age,返回给用户。

    这样做的好处是,同样大小的sort buffer可以放更多的记录,尽可能的在内存中完成操作,代价是会多一次回表取其余字段。

    借助联合索引

    如果选出来的结果是天然有序的,那么我们就不用再做额外排序了。因为索引是天然有序的,所以可以创建city和name的联合索引,这样选出来的结果自然是按照name排序的了

    alter table t add index city_user(city, name);
    select name, age, city from t where city='杭州' limit 1000;

    具体的执行过程就不分析了。如果想避免一次回表去读取age字段,也可以讲索引改成如下,这就是覆盖索引。

    1 alter table t add index city_user(city, name, age);
  • 相关阅读:
    SpringBoot 日志
    springboot 自动配置
    性能测试步骤
    性能测试与压力测试
    Shell学习八:调用其它shell文件
    Shell学习七:重定向
    Linux mysql服务重启
    Shell学习六:流程控制
    Shell学习五:test参数的使用
    Shell学习四:echo和print输出
  • 原文地址:https://www.cnblogs.com/howo/p/13334046.html
Copyright © 2011-2022 走看看