今天给各位分享orderby的知识,其中也会对orderby升序降序进行解释,如果小编能碰巧解决你现在面临的问题,请继续阅读吧!
本文目录一览:
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`city` varchar(16) NOT NULL,
`name` varchar(16) NOT NULL,
`age` int(11) NOT NULL,
`addr` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `city` (`city`)
) ENGINE=InnoDB;
select city,name,age from t where city='杭州' order by name limit 1000 ;
MySQL 会给每个线程分配一块内存用于排序,称为 sort_buffer。
在全字段排序的情况下,这如贺闭个语句执行流程如下所示 :
1)初始化 sort_buffer,确定放入 name、city、age 这三个字段;
2) 从索引 city 找到第一个满足 city='杭州’条件的主键 id
3)到主键 id 索引取出整行,取 name、city、age 三个字段的值,存入 sort_buffer 中;
4)从索引 city 取下一个记录的主键 id;
5) 重复步骤 3、4 直到 city 的值不满足查询条件为止,对应的主键 id
6)对 sort_buffer 中的数据按照字段渣裂 name 做快速排序;
7)按照排序结果取前 1000 行返回给客户端。
图中“按 name 排序”这个动作,可能在内存中完成,也可能需要使用外部排序,这 取决
于排序所需的内存和参数 sort_buffer_size 。
sort_buffer_size,就是 MySQL 为排序开辟的内存(sort_buffer)的大小。如果要排序
的数据量小于 sort_buffer_size,排序就在内存中完成。但如果排序数据量太大,内存放
不下,则不得不利用磁盘临时文件辅助排序。
通过查看 OPTIMIZER_TRACE 来查看排序的结果:
number_of_tmp_files 表示的是,排序过程中使用的临时文件数。你一定奇怪,为什么需
要 12 个文件?内存放不下时,就需要使用外部排序, 外部排序一般使用归并排序算法 。
可以这么简单理解,MySQL 将需要排序的数据分成 12 份,每一份单独排序后存在这些临
时文件中。然后把这 12 个有序文件再合并成一个有序的大文件。
如果 sort_buffer_size 超过了需要排序的数据量的大小,number_of_tmp_files 就是 0,
表示排序可以直接在内存中完成。
否则就需要放在临时文件中排序。sort_buffer_size 越小,需要分成的份数越多,
number_of_tmp_files 的值就越大。
examined_rows=4000,表示参与排序的行数是 4000 行。
结论:
只对原表的数据读了一遍,剩下的操作都是在 sort_buffer 和
临时文件中执行的。但这个算法有一个问题,就是如果查询要拍碰返回的字段很多的话,那么
sort_buffer 里面要放的字段数太多,这样内存里能够同时放下的行数很少,要分成很多个
临时文件,排序的性能会很差。
所以如果单行很大,这个方法效率不够好。
如果 MySQL 认为排序的单行长度太大会怎么做呢?
SET max_length_for_sort_data = 16;
max_length_for_sort_data,是 MySQL 中专门控制用于排序的行数据的长度的一个参
数。它的意思是,如果单行的长度超过这个值,MySQL 就认为单行太大,要换一个算
法。
新的算法(rowid)放入 sort_buffer 的字段,只有要排序的列(即 name 字段)和主键 id。
rowid排序的流程:
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 排序多访问了一次表 t 的主键索引。
需要说明的是,最后的“结果集”是一个逻辑概念,实际上 MySQL 服务端从排序后的
sort_buffer 中依次取出 id,然后到原表查到 city、name 和 age 这三个字段的结果,不
需要在服务端再耗费内存存储结果,是直接返回给客户端的。
sort_mode 变成了,表示参与排序的只有 name 和 id 这两个字段。
number_of_tmp_files 变成 10 了,是因为这时候参与排序的行数虽然仍然是 4000
行,但是每一行都变小了,因此需要排序的总数据量就变小了,需要的临时文件也相应
地变少了。
3. 全字段排序 VS rowid 排序
如果 MySQL 实在是担心排序内存太小,会影响排序效率,才会采用 rowid 排序算法,这
样排序过程中一次可以排序更多行,但是需要再回到原表去取数据。
如果 MySQL 认为内存足够大,会优先选择全字段排序,把需要的字段都放到 sort_buffer
中,这样排序后就会直接从内存里面返回查询结果了,不用再回到原表去取数据。
这也就体现了 MySQL 的一个设计思想:如果内存够,就要多利用内存,尽量减少磁盘访
问。
对于 InnoDB 表来说,rowid 排序会要求回表多造成磁盘读,因此不会被优先选择。
如果上面的例子建立(city, name)的联合索引,本身就是已经排好序的。
如果建立的是覆盖索引,则效率会更高。
MySQL 的表是用什么方法来定位“一行数据”的?
创建的表没有主键,或者把一个表的主键删掉了,那么 InnoDB 会自己生成一个长度为 6 字节的 rowid 来作为主键。
这也就是排序模式里面,rowid 名字的来历。实际上它表示的是:每个引擎用来唯一标识数据行的信息。
对于有主键的 InnoDB 表来说,这个 rowid 就是主键 ID;
对于没有主键的 InnoDB 表来说,这个 rowid 就是由系统生成的;
order by rand() 使用了内存临时表,内存临时表排序的时候使用了 rowid 排序方法。
磁盘临时表
tmp_table_size 这个配置限制了内存临时表的大小,默认值是 16M。
如果临时表大小超过了 tmp_table_size,那么内存临时表就会转成磁盘临时表。
磁盘临时表使用的引擎默认是 InnoDB,是由参数 internal_tmp_disk_storage_engine
控制的。
MySQL 5.6 版本引入的一个新的排序算法,即: 优先队列排序算法 。
什么时候采用优先队列排序算法?
当返回的数据结果集小于sort_buffer_size的大小时,采用 优先队列排序算法,此时,不需要临时文件,所以,number_of_tmp_files = 0
什么时候采用用临时文件的算法,也就是归并排序算法?
比如返回的结果 limit 10000,超过了sort_buffer_size的大小,只能采用 归并排序算法。
说明:优先队列排序算法与归并算法是结果集的排序算法,跟全字段排序与rowid排序不是一回事。
前言
日常开发中,我们经常会使用到order by,亲爱的小伙伴,你是否知道order by 的工作原理呢?order by的优化思路是怎样的呢?使用order by有哪些注意的问题呢?本文将跟大家一起来学习,攻克order by~
一个使用order by 的简单例子
假设用一张员工表,表结构如下:
表数据如下:
我们现在有这么一个需求:查询前10个,来自深圳员工的姓名、年龄、城市,并且按照年龄小到大排序。对应的 SQL 语句就可以这么写:
这条语句的逻辑很清楚,但是它的底层执行流程是怎样的呢?
order by 工作原理
explain 执行计划
我们先用Explain关键字查看一下执行计划
我们可以发现,这条SQL使用到了索引,并且也用到排序。那么它是怎么排序的呢?
全字段排序
MySQL 会给每个查询线程分配一块小内存,用于排序的,称为 sort_buffer。什么时候把字段放进去排序呢,其实是通过idx_city索引找到对应的数据,才把数据放进去啦。
我们回顾下索引是怎么找到匹配的数据的,现在先指搜虚把索引树画出来吧,idx_city索引树如下:
idx_city索引树,叶子节点存储的是主键id。还有一棵id主键聚族索引树,我们再画出聚族索引树图吧:
我们的查询语句是怎么找到匹配数据的呢?先通过idx_city索引漏高树,找到对应的主键id,然后再通过拿到的主键id,搜索id主键索引树,找到对应的行数据。
加上order by之后,整体的执行流程就是:
执行示意图如下:
将查询所需的字段全部读取到sort_buffer中,就是全字段排序。这里面,有些小伙伴可能会有个疑问,把查询的所有字段都放到sort_buffer,而sort_buffer是一块内存来的,如果数据量太大,sort_buffer放不下怎么办呢?
磁盘临时文件辅助排序
实际上,sort_buffer的大小是由一个参数控制的:sort_buffer_size。如果要排序的数据小于sort_buffer_size,排序在sort_buffer 内存中完成,如果要排序的数据大于sort_buffer_size,则借助磁盘文件来进行排序
如何确定是否使用了磁盘文件来进行排序呢?可以使用以下这几个命令
可以从 number_of_tmp_files 中看出,是否使用了临时文件。
number_of_tmp_files 表示使用来排序的磁盘临时文件数。如果number_of_tmp_files0,则表示使用了磁盘文件来进行排序。
使用了磁盘临时文件,整个排序过程又是怎样的呢?
TPS: 借助磁盘临时小文件排序,实际上使用的是归并排序算法。
小伙伴们可能会有个疑问,既然sort_buffer放不下,就需要用到临时磁盘文件,这会影响排序效率。那为什么还要把排序不相关的字段(name,city)放到sort_buffer中呢?只放排序相关的age字段,它不香吗?可以了解下rowid 排序。
rowid 排序
rowid 排序就是,只把查询SQL需要用于排序的字段和主键id,放到sort_buffer中。那怎么确定走的是全字段排序还是rowid 排序排序呢?
实际上有个参数控制的。这个参数就是max_length_for_sort_data,它表示MySQL用于排序行数据的长度的一个参数,如果单行的长度超过这个值,MySQL 就认为单行太大,就换rowid 排序。我们可以通过命令看下这个参数取值。
max_length_for_sort_data 默认值是1024。因为本文示例中name,age,city长度=64+4+64 =132 1024, 所以走的是全字段排序。我们来改下这个参数,改小一点.
使用rowid 排序的话,整个SQL执行流程又是怎样的呢?
执行示意图如下唯燃:
对比一下全字段排序的流程,rowid 排序多了一次回表。
什么是回表?拿到主键再回到主键索引查询的过程,就叫做回表”
我们通过optimizer_trace,可以看到是否使用了rowid排序的:
全字段排序与rowid排序对比
一般情况下,对于InnoDB存储引擎,会优先使用全字段排序。可以发现 max_length_for_sort_data 参数设置为1024,这个数比较大的。一般情况下,排序字段不会超过这个值,也就是都会走全字段排序。
order by的一些优化思路
我们如何优化order by语句呢?
联合索引优化
再回顾下示例SQL的查询计划
我们给查询条件city和排序字段age,加个联合索引idx_city_age。再去查看执行计划:
可以发现,加上idx_city_age联合索引,就不需要Using filesort排序了。为什么呢?因为索引本身是有序的,我们可以看下idx_city_age联合索引示意图,如下:
整个SQL执行流程变成酱紫:
流程示意图如下:
从示意图看来,还是有一次回表操作。针对本次示例,有没有更高效的方案呢?有的,可以使用覆盖索引:
覆盖索引:在查询的数据列里面,不需要回表去查,直接从索引列就能取到想要的结果。换句话说,你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是否需要加索引:
无条件查询的话,即使create_time上有索引,也不会使用到。因为MySQL优化器认为走普通二级索引,再去回表成本比全表扫描排序更高。所以选择走全表扫描,然后根据全字段排序或者rowid排序来进行。
如果查询SQL修改一下:
分页limit过大时,会导致大量排序怎么办?
假设SQL如下:
索引存储顺序与order by不一致,如何优化?
假设有联合索引 idx_age_name, 我们需求修改为这样:查询前10个员工的姓名、年龄,并且按照年龄小到大排序,如果年龄相同,则按姓名降序排。对应的 SQL 语句就可以这么写:
我们看下执行计划,发现使用到Using filesort
这是因为,idx_age_name索引树中,age从小到大排序,如果age相同,再按name从小到大排序。而order by 中,是按age从小到大排序,如果age相同,再按name从大到小排序。也就是说,索引存储顺序与order by不一致。
我们怎么优化呢?如果MySQL是8.0版本,支持Descending Indexes,可以这样修改索引:
使用了in条件多个属性时,SQL执行是否有排序过程
如果我们有联合索引idx_city_name,执行这个SQL的话,是不会走排序过程的,如下:
但是,如果使用in条件,并且有多个条件时,就会有排序过程。
这是因为:in有两个条件,在满足深圳时,age是排好序的,但是把满足上海的age也加进来,就不能保证满足所有的age都是排好序的。因此需要Using filesort。
order by 是排序的意思。order by 列名腊枝伏1,列名2,..... 你按照什么排序就写什么列。 如果列名后什么搭戚都不写,也可以写ASC,表示升序排列,如果要想降序排列,在列名后面写desc 。
order by是什么意思
order by 从英文里理解就是行的排序方式,默认的为升序。 order by 后面必须列出排序的字段名,可以是多个字段名。
group by 从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志字段。
在使用group by的语句中,只能select用于分类的列(表达式),或聚合函数。
where条件用于group by之前,having用于group by 之后对结果进行筛选。
order用法
一、名词order:
1、作“顺序”、“次序”。常用短语:in order of 按顺序。如:
A list of some of the common metals in the order of their activity is given below. 下面列出了某些金属按其活泼顺序排列的一个表格.
2、作“秩序”。常用短语:keep ... in order 使......有序。如:
The machine is in good working order. 机器运转良好.
Our laboratory is kept in good order. 我们的实验室保持整齐.(句中in good order为主语补语.)
3、作“指示、命令”。常用短语:give sb. anorderto do sth.命令某人做某事。如:
He gave orders for the work to be started. (=…orders that the work should be started.)他下令开始工作.
4、点菜;所点的饮食菜肴。
二、动词order:
1、作”命令”。轮携常用短语:ordersb.to do sth. 令某人做某事。如:
The doctor ordered him to stay there.医生嘱咐他留在那里。(不定式短语to stay there作宾语补语)
2、作“点餐、“订购”。常用短语:ordersth.for sb./ordersb.for sth.为某人订购/点某物。如:
They have ordered 1,000 oil pumps from our factory.他们已向我厂订购1,000台油泵。
来源:网络。本文版权归原创作者所以。
在计算机中:
order by 从英文里理解就是行的排序方式,默认的为升序。 order by
后面必须列出排序的字段名,可以是多个字段名。
group by
从英文里理解就是分组。必须有“聚合函数”来配合才渗埋能使用,使用时至少需要一个分组标志字段。
作为英语:
order by 排序;排序依据;分组排序
例句:
1.An index will be used for both an ascending and a descending ORDER BY,whether the index was ascending or descending.
不管索引是升序排列还是降序排列,在执行升序或降序ORDERBY操作时都会使用索引。
2.Analytic functions are the last set of operations performed in a query except for the final ORDER BY clause.
除了ORDERBY(按…排序)语句外,分析函数是一条查询被执行的操作。
group by分组;将表按行分组;分组依据
例句:
1.The List To Group projection can only be used for lists, and it turns the list into agroup by retaining only the first item of the list.
ListToGroup映射仅可用于列表,敬铅它通过仅保留列表的第一个项目将列表转化成一个组。
2.Indicates that the data column is being used to create a grouped result set (ispart of a GROUP BY clause) in an aggregate query.
表示亮喊好数据列用于在聚合查询中创建分组的结果集(GROUPBY子句的一部分)。
order by 是排序的意思。
order by 列名1,列名2,..... 你按照什兄历么排序就写什么列。 如果列名后什么都不写,也可以核轮写ASC,表示升序排羡氏搜列,如果要想降序排列,在列名后面写desc 。
以上就是关于orderby的全部介绍,更多有关orderby升序降序的高三知识,欢迎持续关注我们的网站。