范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

对orderby的理解

  前言
  日常开发中,我们经常会使用到order by,亲爱的小伙伴,你是否知道order by 的工作原理呢?order by的优化思路是怎样的呢?使用order by有哪些注意的问题呢?本文将跟大家一起来学习,攻克order by~
  一个使用order by 的简单例子
  假设用一张员工表,表结构如下: CREATE TABLE `staff` (   `id` BIGINT ( 11 ) AUTO_INCREMENT COMMENT "主键id",   `id_card` VARCHAR ( 20 ) NOT NULL COMMENT "身份证号码",   `name` VARCHAR ( 64 ) NOT NULL COMMENT "姓名",   `age` INT ( 4 ) NOT NULL COMMENT "年龄",   `city` VARCHAR ( 64 ) NOT NULL COMMENT "城市",   PRIMARY KEY ( `id`),   INDEX idx_city ( `city` )   ) ENGINE = INNODB COMMENT "员工表";
  表数据如下:
  我们现在有这么一个需求:查询前10个,来自深圳员工的姓名、年龄、城市,并且按照年龄小到大排序。对应的 SQL 语句就可以这么写: select name,age,city from staff where city = "深圳" order by age limit 10;
  这条语句的逻辑很清楚,但是它的底层执行流程是怎样的呢?
  order by 工作原理
  explain 执行计划
  我们先用Explain关键字查看一下执行计划
  执行计划的key这个字段,表示使用到索引idx_city Extra 这个字段的 Using index condition 表示索引条件 Extra 这个字段的 Using filesort表示用到排序
  我们可以发现,这条SQL使用到了索引,并且也用到排序。那么它是怎么排序的呢?
  全字段排序
  MySQL 会给每个查询线程分配一块小内存,用于排序的,称为 sort_buffer。什么时候把字段放进去排序呢,其实是通过idx_city索引找到对应的数据,才把数据放进去啦。
  我们回顾下索引是怎么找到匹配的数据的,现在先把索引树画出来吧,idx_city索引树如下:
  idx_city索引树,叶子节点存储的是主键id。还有一棵id主键聚族索引树,我们再画出聚族索引树图吧:
  我们的查询语句是怎么找到匹配数据的呢?先通过idx_city索引树,找到对应的主键id,然后再通过拿到的主键id,搜索id主键索引树,找到对应的行数据。
  加上order by之后,整体的执行流程就是: MySQL 为对应的线程初始化sort_buffer,放入需要查询的name、age、city字段; 从索引树idx_city, 找到第一个满足 city="深圳’条件的主键 id,也就是图中的id=9; 到主键 id 索引树拿到id=9的这一行数据, 取name、age、city三个字段的值,存到sort_buffer; 从索引树idx_city 拿到下一个记录的主键 id,即图中的id=13; 重复步骤 3、4 直到city的值不等于深圳为止; 前面5步已经查找到了所有city为深圳的数据,在 sort_buffer中,将所有数据根据age进行排序; 按照排序结果取前10行返回给客户端。
  执行示意图如下:
  将查询所需的字段全部读取到sort_buffer中,就是全字段排序。这里面,有些小伙伴可能会有个疑问,把查询的所有字段都放到sort_buffer,而sort_buffer是一块内存来的,如果数据量太大,sort_buffer放不下怎么办呢?
  磁盘临时文件辅助排序
  实际上,sort_buffer的大小是由一个参数控制的:sort_buffer_size。如果要排序的数据小于sort_buffer_size,排序在sort_buffer 内存中完成,如果要排序的数据大于sort_buffer_size,则借助磁盘文件来进行排序
  如何确定是否使用了磁盘文件来进行排序呢?可以使用以下这几个命令 ## 打开optimizer_trace,开启统计   set optimizer_trace = "enabled=on";   ## 执行SQL语句   select name,age,city from staff where city = "深圳" order by age limit 10;   ## 查询输出的统计信息   select * from information_schema.optimizer_trace
  可以从 number_of_tmp_files 中看出,是否使用了临时文件。
  number_of_tmp_files 表示使用来排序的磁盘临时文件数。如果number_of_tmp_files>0,则表示使用了磁盘文件来进行排序。
  使用了磁盘临时文件,整个排序过程又是怎样的呢? 从主键Id索引树,拿到需要的数据,并放到sort_buffer内存块中。当sort_buffer快要满时,就对sort_buffer中的数据排序,排完后,把数据临时放到磁盘一个小文件中。 继续回到主键 id 索引树取数据,继续放到sort_buffer内存中,排序后,也把这些数据写入到磁盘临时小文件中。 继续循环,直到取出所有满足条件的数据。最后把磁盘的临时排好序的小文件,合并成一个有序的大文件。
  TPS: 借助磁盘临时小文件排序,实际上使用的是归并排序算法。
  小伙伴们可能会有个疑问,既然sort_buffer放不下,就需要用到临时磁盘文件,这会影响排序效率。那为什么还要把排序不相关的字段(name,city)放到sort_buffer中呢?只放排序相关的age字段,它不香吗?可以了解下rowid 排序。
  rowid 排序
  rowid 排序就是,只把查询SQL需要用于排序的字段和主键id,放到sort_buffer中。那怎么确定走的是全字段排序还是rowid 排序排序呢?
  实际上有个参数控制的。这个参数就是max_length_for_sort_data,它表示MySQL用于排序行数据的长度的一个参数,如果单行的长度超过这个值,MySQL 就认为单行太大,就换rowid 排序。我们可以通过命令看下这个参数取值。 show variables like "max_length_for_sort_data";
  max_length_for_sort_data 默认值是1024。因为本文示例中name,age,city长度=64+4+64 =132 < 1024, 所以走的是全字段排序。我们来改下这个参数,改小一点. ## 修改排序数据最大单行长度为32   set max_length_for_sort_data = 32;   ## 执行查询SQL   select name,age,city from staff where city = "深圳" order by age limit 10;
  使用rowid 排序的话,整个SQL执行流程又是怎样的呢? MySQL 为对应的线程初始化sort_buffer,放入需要排序的age字段,以及主键id; 从索引树idx_city, 找到第一个满足 city="深圳’条件的主键 id,也就是图中的id=9; 到主键 id 索引树拿到id=9的这一行数据, 取age和主键id的值,存到sort_buffer; 从索引树idx_city 拿到下一个记录的主键 id,即图中的id=13; 重复步骤 3、4 直到city的值不等于深圳为止; 前面5步已经查找到了所有city为深圳的数据,在 sort_buffer中,将所有数据根据age进行排序; 遍历排序结果,取前10行,并按照 id 的值回到原表中,取出city、name 和 age 三个字段返回给客户端。
  执行示意图如下:
  对比一下全字段排序的流程,rowid 排序多了一次回表。
  什么是回表?拿到主键再回到主键索引查询的过程,就叫做回表"
  我们通过optimizer_trace,可以看到是否使用了rowid排序的: ## 打开optimizer_trace,开启统计   set optimizer_trace = "enabled=on";   ## 执行SQL语句   select name,age,city from staff where city = "深圳" order by age limit 10;   ## 查询输出的统计信息   select * from information_schema.optimizer_trace
  全字段排序与rowid排序对比 全字段排序:sort_buffer内存不够的话,就需要用到磁盘临时文件,造成磁盘访问。 rowid排序:sort_buffer可以放更多数据,但是需要再回到原表去取数据,比全字段排序多一次回表。
  一般情况下,对于InnoDB存储引擎,会优先使用全字段排序。可以发现 max_length_for_sort_data 参数设置为1024,这个数比较大的。一般情况下,排序字段不会超过这个值,也就是都会走全字段排序。
  order by的一些优化思路
  我们如何优化order by语句呢? 因为数据是无序的,所以就需要排序。如果数据本身是有序的,那就不用排了。而索引数据本身是有序的,我们通过建立联合索引,优化order by 语句。 我们还可以通过调整max_length_for_sort_data等参数优化;
  联合索引优化
  再回顾下示例SQL的查询计划 explain select name,age,city from staff where city = "深圳" order by age limit 10;
  我们给查询条件city和排序字段age,加个联合索引idx_city_age。再去查看执行计划: alter table staff add  index idx_city_age(city,age);   explain select name,age,city from staff where city = "深圳" order by age limit 10;
  可以发现,加上idx_city_age联合索引,就不需要Using filesort排序了。为什么呢?因为索引本身是有序的,我们可以看下idx_city_age联合索引示意图,如下:
  整个SQL执行流程变成酱紫: 从索引idx_city_age找到满足city="深圳’ 的主键 id 到主键 id索引取出整行,拿到 name、city、age 三个字段的值,作为结果集的一部分直接返回 从索引idx_city_age取下一个记录主键id 重复步骤 2、3,直到查到第10条记录,或者是不满足city="深圳’ 条件时循环结束。
  流程示意图如下:
  从示意图看来,还是有一次回表操作。针对本次示例,有没有更高效的方案呢?有的,可以使用覆盖索引:
  覆盖索引:在查询的数据列里面,不需要回表去查,直接从索引列就能取到想要的结果。换句话说,你SQL用到的索引列数据,覆盖了查询结果的列,就算上覆盖索引了。"
  我们给city,name,age 组成一个联合索引,即可用到了覆盖索引,这时候SQL执行时,连回表操作都可以省去啦。
  调整参数优化
  我们还可以通过调整参数,去优化order by的执行。比如可以调整sort_buffer_size的值。因为sort_buffer值太小,数据量大的话,会借助磁盘临时文件排序。如果MySQL服务器配置高的话,可以使用稍微调整大点。
  我们还可以调整max_length_for_sort_data的值,这个值太小的话,order by会走rowid排序,会回表,降低查询性能。所以max_length_for_sort_data可以适当大一点。
  当然,很多时候,这些MySQL参数值,我们直接采用默认值就可以了。
  使用order by 的一些注意点:没有where条件,order by字段需要加索引吗
  日常开发过程中,我们可能会遇到没有where条件的order by,那么,这时候order by后面的字段是否需要加索引呢。如有这么一个SQL,create_time是否需要加索引: select * from A order by create_time;
  无条件查询的话,即使create_time上有索引,也不会使用到。因为MySQL优化器认为走普通二级索引,再去回表成本比全表扫描排序更高。所以选择走全表扫描,然后根据全字段排序或者rowid排序来进行。
  如果查询SQL修改一下: select * from A order by create_time limit m; 无条件查询,如果m值较小,是可以走索引的.因为MySQL优化器认为,根据索引有序性去回表查数据,然后得到m条数据,就可以终止循环,那么成本比全表扫描小,则选择走二级索引。
  分页limit过大时,会导致大量排序怎么办?
  假设SQL如下: select * from A order by a limit 100000,10 可以记录上一页最后的id,下一页查询时,查询条件带上id,如:where id > 上一页最后id limit 10。 也可以在业务允许的情况下,限制页数。
  索引存储顺序与order by不一致,如何优化?
  假设有联合索引 idx_age_name, 我们需求修改为这样:查询前10个员工的姓名、年龄,并且按照年龄小到大排序,如果年龄相同,则按姓名降序排。对应的 SQL 语句就可以这么写: select name,age from staff  order by age ,name desc limit 10;
  我们看下执行计划,发现使用到Using filesort
  这是因为,idx_age_name索引树中,age从小到大排序,如果age相同,再按name从小到大排序。而order by 中,是按age从小到大排序,如果age相同,再按name从大到小排序。也就是说,索引存储顺序与order by不一致。
  我们怎么优化呢?如果MySQL是8.0版本,支持Descending Indexes,可以这样修改索引: CREATE TABLE `staff` (     `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT "主键id",     `id_card` varchar(20) NOT NULL COMMENT "身份证号码",     `name` varchar(64) NOT NULL COMMENT "姓名",     `age` int(4) NOT NULL COMMENT "年龄",     `city` varchar(64) NOT NULL COMMENT "城市",     PRIMARY KEY (`id`),     KEY `idx_age_name` (`age`,`name` desc) USING BTREE   ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT="员工表";
  使用了in条件多个属性时,SQL执行是否有排序过程
  如果我们有联合索引idx_city_name,执行这个SQL的话,是不会走排序过程的,如下: select * from staff where city in ("深圳") order by age limit 10;
  但是,如果使用in条件,并且有多个条件时,就会有排序过程。 explain select * from staff where city in ("深圳","上海") order by age limit 10;
  这是因为:in有两个条件,在满足深圳时,age是排好序的,但是把满足上海的age也加进来,就不能保证满足所有的age都是排好序的。因此需要Using filesort。
  对order by的理解 | 《Linux就该这么学》 (linuxprobe.com)

乐视发布回归后的首款手机S1,内置华为HMS生态继今年五月份乐视宣布重新进军手机领域后,一直没有乐视手机新的消息。27日下午乐视举办了媒体沟通会,在沟通会上,乐视展示了四款S1工程机。该机采用720P级水滴屏,搭载虎贲T7510美国政客针对是否要制裁新荣耀,又展开一轮激烈的争论是否要制裁新荣耀,从荣耀正式被华为出售后就一直没有停止过,鹰派美国政府议员通过各种提案来讨论制裁已经从华为完全剥离出来的新荣耀。近日,根据华盛顿邮报的报道称,美国安全机构正在讨论是搜狗正式成为腾讯子公司北京时间9月24日(美国东部时间9月23日),搜狗公司发布公告宣布与腾讯完成合并。合并完成后,搜狗公司将成为腾讯控股的间接全资子公司,并完成美国退市。此前7月13日,国家市场监管总vivo打造107研发制造体系,解锁行业新风向Vivo作为国产手机品牌正在崛起,始终致力于生产出符合消费者需求的产品,被网友评为最懂消费者的手机品牌,vivo不断深耕和探索,自主研发的专业影像芯片V1极夜微缝式补光灯微云台防抖音响系统中线材的作用有多重要?阜新声艺视听1hr导线的构造介绍在比较导线的好坏之前,我们要先对它的构造有最基本的认知。01hr线芯(Conductor)导线中的线芯是导体,负责讯号的传送,是整条导线的灵魂。导线的设计可以分舞台!到底有什么奥秘?阜新声艺视听在这一期的文章里面,要来跟大家探讨一下舞台上到底有哪些撇步可以让各位演出者能更加在舞台上如鱼得水的演出。但是跟大家聊聊舞台上的奥秘之前,想先跟大家聊聊PA是甚么?PA是由Publi双雄探案,层层反转,这新剧靠口碑成功逆袭阜新声艺视听近期最火的刑侦剧,当属窥探莫属。别说猜不到凶手了,就算看剧情,都看的一脸懵与它同期播出的,也有一部同类型的新剧。层层深入,环环相扣,越看越上头。虽然有些晚了,今天就来聊聊它怪物导演从本届广州国际专业灯光音响展看出的几大趋势19届广州国际专业灯光音响展进入第三天。从整体来看,本届展会坚持以聚焦国内市场积极布局海外市场,积极引入数字技术媒体融合智能制造等创新音响行业发展元素,吸引力广泛关注。整个展会划分音频压缩器及其使用阜新声艺视听你可能是第一次接触压缩器,又或者你已经有多年混音经验,以下的内容希望可以帮助各位更明白压缩器及简单分享笔者用压缩器的心得和一些小秘方。压缩器自动音量调教器压缩器,这个字可能比较神秘灯光设备的维修保养阜新声艺视听设备的寿命在很大程度上决定于维护保养的好坏。灯光设备的维修保养较为复杂,也比较琐碎,基本上需做到每天的常规检测每周的定期检测每月的设备保养及适当调试。本期明和小课堂,小编将带大家一限幅器基本概念以及设置方法阜新声艺视听01hr介绍这篇文章的主旨是帮助广大用户更好的理解如何使用Powersoft功放DSP当中不同种类的限幅器。这篇文章所描述的内容适用于Powersoft以下产品型号X系列,T系列,
从5999跌至3489,三星2K屏IP68防水,小众品牌的大众心前华为荣耀副总裁李开新加入一加手机,担任一加副总裁后,就马不停蹄地对一加手机进行销售方案的计划,欲将一加手机打造成为大众品牌,目前一加仍然是小众品牌,跟华为小米OPPO和vivo等雷丁芒果正式上市售价2。985。49万元日前,第一电动网从相关渠道获悉,雷丁芒果正式上市,售价区间为2。985。49万元。作为一款A00级别纯电动微型车,在此前给人的印象一直属于是低速电动车,此次升级改款后,在设计上已经小米MIX真的要来了屏下镜头四面等宽直角全屏200W全快充在2019年雷军宣布小米品牌和红米品牌分割,小米品牌背负小米冲击高端品牌的重任。并且还为小米手机重新划分了品牌定位,分别为定位高端的小米数字系列,定位年轻人拍照手感颜值的小米CC系消费者报告将特斯拉Model3的首选评级下调特斯拉决定Model3和ModelY车型中删除雷达传感器的决定,使该公司付出了受到广泛关注的保险行业组织和颇具影响力的消费者报告杂志的最高安全评级调整的代价。美国国家公路交通安全管李彦宏为什么不把百度搬去山西太原?因为他脑子还是很清醒的如果李彦宏还有理智的话,就千万不要把百度搬到山西太原去。太原市这个地方虽然说是一个省会城市,但是,无论是硬件设施还是软件设施等等都不利于百度这样一个世界级企业鸿蒙OS以赛促学课程进校背后开发者成为生态的第一批种子经济观察网记者钱玉娟实习记者刘雨琪5月24日,在深圳举办的首届HarmonyOS开发者创新大赛颁奖礼中,一位来自河北承德,年仅9岁的小学生吸引了大家的注意力,他的名字叫戈帅。实际上华为EMUI9。1官宣今晚见华为P30系列将于3月26日北京时间2100(巴黎时间1400)发布,包括P30P30ProP30Lite(国际版的nova4e)。日前,华为EMUI官方微博宣布,EMUI9。1也链家终于掏空了链家!3月25日,有消息传出,北京链家房地产经纪公司(以下简称链家)近日发生注册资本投资人和管理层变化,包括万科腾讯百度高瓴资本融创中国等在内的22家投资人撤出投资,公司注册资本由205内存智能存储降价太狠,三星发警告了从去年10月份内存价格由涨转跌之后,全球存储芯片市场的牛市就结束了,而且是急转直下,今年2月更是罕见地出现了价格大幅下跌,而且季度跌幅从原先预估的25调整至接近30,创下2011年终于等到你!四部委发布2019新能源汽车补贴政策68客车降幅最惨第一商用车网原创2019年新能源汽车补贴政策终于发布!今天(3月26日),财政部联合工信部科技部和发改委发布关于进一步完善新能源汽车推广应用财政补贴政策的通知。通知显示,2019年拉卡拉成功过会去年营收57亿雷军持股1雷帝网乐天3月26日报道第三方支付公司拉卡拉支付股份有限公司于今日成功过会,预计未来几个月在国内上市。招股书显示,拉卡拉2016年2017年2018年营收分别为25。6亿27。85