一.MYSQL 中有两种排序方式:
1:通过有序索引顺序扫描直接返回有序数据,这种方式在使用explain 分析查询的时候显示为Using Index ,不需要额外的排序,操作效率较高。
2: 是通过对返回数据进行排序,也就是通常说的filesort 排序,所有不是通过索引直接返回排序结果都叫filesort排序。filesort 并不代表磁盘文件进行排序,而只是说明了进行一个排序操作,至于排序操作是否使用了磁盘文件或临时表等,则取决于mysql 服务器对排序参数的设置和需要排序数据的大小。例如,按照商店store_id 排序返回所有客户记录时,出现了对全表扫描的结果排序:
explain select * from customer order by store_id
Extra : Using filesort
 
又如,只需要获取商店store_id 和顾客email 信息时,对表customer 的扫描就被覆盖索引idx_storeid_email 扫描替代,此时虽然只访问了索引就足够,但是在索引idx_stored_email 上发生了一次排序操作,所以执行计划仍然有 using filesort.
alter table customer add index idx_storeid_email(store_id,email);
 
explain select store_id ,email ,customer_id from customer order by email
extra :Using Index ,Using filesort
 
 
Filesort 是通过相应的排序算法,将取得的数据在sort_buffer_size 系统变量设置的内存排序区中进行排序,如果内存装载不下,它就会将磁盘上的数据进行分区,再对各个数据块进行排序,然后将各个块合并成有序的结果集。sort_buffer_size 设置的排序区是每个线程独占的,所以同一个时刻,mysql 中存在多个sort buffer 排序区.
 
了解了mysql 排序的方式,优化目标就清晰了:尽量减少额外的排序,通过索引直接返回有序数据。where 条件和order by 使用相同的索引,并且order by 的顺序和索引顺序相同,并且order by 的字段都是生序或者都是降序,否则肯定需要额外的排序操作,这样就会出现filesort.
总结,下列SQL 可以使用索引:
select * from tabname order by key_part1,key_part2,......;
select * from tabname where key_part1 order by key_part1 desc ,key_part2 desc;
select * from tabname order by key_part1,key_part2 desc;
 
但是在以下几种情况下则不使用 索引:
 
select * from tabname order by key_part1 desc ,key_part2 asc;
-- order by 的字段混合ASC 和 DESC
select * from tabname where key2=constant order by key1;
-- 用于查询行的关键字与order by 中所使用的不相同
select * from tabname order by key1,key2;
-- 对不同的关键字使用order by :
 
 
二.Filesort 的优化
通过创建合适的索引能够减少filesort 出现,但是在某些情况下,条件限制不能让filesort 消失,那就需要想办法加快 filesort 的操作。对于filesort ,MYSQL 有两种排序算法。
1.两次扫描算法(Two passes):首先根据条件取出排序字段和行指针信息,之后在排序区sort buffert 中排序。如果排序区sort buffer 不够,则在临时表temporary table 中存储排序结果。完成排序后根据行指针回表读取记录。该算法是mysql 4.1 之前采用的算法,需要两次访问数据,第一次获取排序字段和行指针信息,第二次根据行指针获取记录,尤其是第二次读取操作可能导致大量随机 I/O 操作;优点是排序的时候内存呢开销哦较少。
 
2. 一次扫描算法(Single pass):一次行取出满足条件的行的所有字段,然后在排序区sort buffer 中排序后直接输出结果集。排序的时候内存开销比较大,但是排序效率比两次扫描算法要高。
 
MySQL 通过比较系统变量 max_length_for_sort_data 的大小和Query 语句取出的字段总大小来判断使用哪种 排序算法。如果 max_length_for_sort_data更大,那么使用第二种优化之后的算法;否则使用第一种算法。
适当加大系统变量max_length_for_sort_data 的值,能够让 mysql 选择更优化的filesort 排序算法。当然,假如 max_length_for_sort_data 设置过大,会造成cpu 利用率过低和磁盘I/ O过高,cpu 和I/O利用平衡就足够了。
 
 
适当加大sort_buffer_size 排序区,尽量让排序在内存中完成,而不是通过创建临时表放在文件中进行;当然也不能无限制加大 sort_buffer_size 排序区,因为sort_buffer_size 参数是每个线程独占的,设置过大,会导致服务器SWAP 严重,要考虑数据库活动连接数和服务器内存的大小来适当设置排序区。
尽量使使用必要的字段,select 具体的字段名称,而不是 select * 选择 所有字段,这样可以减少排序区的使用,提高SQL 性能。
 
三. 优化 Group BY 语句
如果查询包含Group by 但用户想要 避免排序结果的消耗,则可以指定order by null 禁止排序。
explain select payment_date,sum(amount) from payment group by payment_fate
extra : Using temporary;Using filesort
 
explain select payment_date,sum(amount) from payment_date order by null
extra : Using temporary
 
 
 
 
 
 

MYSQL 排序和分组的更多相关文章

  1. MySQL的外键,修改表,基本数据类型,表级别操作,其他(条件,通配符,分页,排序,分组,联合,连表操作)

    MySQL的外键,修改表,基本数据类型,表级别操作,其他(条件,通配符,分页,排序,分组,联合,连表操作): a.创建2张表 create table userinfo(nid int not nul ...

  2. MySql下实现先排序后分组

    最近在工作中遇到一个先排序后分组的需求,发现MySql不同的版本有不同的结果,特此记录. 举例:要求在shop表中查询出各类型商店中价格最高的商品. --表结构-- create table `sho ...

  3. mysql 怎样先排序再分组

    权游游牧族:众所周知!一句SqL语句不能先排序再分组.所以这里给出几个案例 --表结构-- create table `shop` ( `id` int (10) PRIMARY KEY, `shop ...

  4. MySQL进阶5--分组函数 / 分组排序和分组查询 group by(having) /order by

    MySQL进阶--分组排序和分组查询 group by(having) /order by /* 介绍分组函数 功能:用做统计使用,又称为聚合函数或组函数 1.分类: sum, avg 求和 /平均数 ...

  5. MySQL最常用分组聚合函数

    一.聚合函数(aggregation function)---也就是组函数 在一个行的集合(一组行)上进行操作,对每个组给一个结果. 常用的组函数: AVG([distinct] expr) 求平均值 ...

  6. ElasticSearch6.0 Java API 使用 排序,分组 ,创建索引,添加索引数据,打分等(一)

    ElasticSearch6.0  Java API  使用     排序,分组 ,创建索引,添加索引数据,打分等 如果此文章对你有帮助,请关注一下哦 1.1 搭建maven 工程  创建web工程 ...

  7. sql中实现先排序后分组

    数据表结构和数据如下: CREATE TABLE `commun_message_chat_single` ( `id` ) NOT NULL AUTO_INCREMENT, `chat_id` ) ...

  8. DQL语句排序与分组

    DQL语句排序与分组 一.DQL-排序 排序是计算机内经常进行的一种操作,其目的是将一组"无序"的记录序列调整为"有序"的记录序列.分内部排序和外部排序,若整个 ...

  9. Hadoop学习笔记—11.MapReduce中的排序和分组

    一.写在之前的 1.1 回顾Map阶段四大步骤 首先,我们回顾一下在MapReduce中,排序和分组在哪里被执行: 从上图中可以清楚地看出,在Step1.4也就是第四步中,需要对不同分区中的数据进行排 ...

随机推荐

  1. Mac通过homebrew 安装mysql

    来源:http://timtang.me/blog/2011/12/07/mac-homebrew-mysql/ 使用MBP有一年了,开始想在工作中使用mac由于各种不习惯最终失败,导致自己使用了一年 ...

  2. C语言移动一个点

    #include"stdio.h"#include"windows.h"#include"conio.h"#define M 3#defin ...

  3. 萌新带你开车上p站(二)

    本文作者:萌新 前情提要:萌新带你开车上p站(一) 0x04flag  看题目描述似乎是一个和脱壳相关的逆向题目 按照给出的地址先下载过来 file看看 是个可执行文件 执行之 emm什么都看不出来, ...

  4. 【C#】写一个支持多人聊天的TCP程序

    碎碎念 先谈谈我们要实现的效果:客户端可以选择要聊天的对象,或者直接广播消息(类似QQ的私聊和群消息) 那么,该如何实现呢? 首先明确的是,要分客户端和服务器端两个部分(废话) 客户端:选择要发送的对 ...

  5. 三、ARP协议和ICMP协议

    一.ARP协议 网络设备有数据要发送到另一台网络设备时,必须要知道对方的网络层地址(IP).IP地址由网络层来提供,但是仅有IP地址是不够的,IP数据报文必须封装成帧才能通过数据链路进行发送.数据帧必 ...

  6. kubernates常用命令

    Kubernetes常用操作命令 kubectl log  //查看日志 $ kubectl log myapp-pod –c test kubectl get pods查看pod列表 [root@n ...

  7. Thymeleaf+SpringBoot+SpringDataJPA实现的中小医院信息管理系统

    项目简介 项目来源于:https://gitee.com/sensay/hisystem 作者介绍 本系统是基于Thymeleaf+SpringBoot+SpringDataJPA实现的的中小医院信息 ...

  8. [原创] 在C++中实现打字机效果

    如题. void pout(string str,int t)//随便取的,不要介意,str是待输出字符串,t是每两个字的间隔时间. { ;i<str.length();i++) { cout& ...

  9. 【Java】InnerClass 内部类

    Java 允许一个类的定义位于另一个类的内部,前者为内部类,后者称为外部类 InnerClass一般定义它的类或语句块之中外部类引用时必须给出完整的名称 成员内部类 & 局部内部类 - 静态成 ...

  10. GeoGebra案例(傅里叶级数的方波)

    傅里叶级数介绍:请移步参见这位马大佬的博文 https://www.matongxue.com/madocs/619.html 马大佬中的gif图在我看来是非常直观且有趣的,奈何本人本领实在有限,学习 ...