工作中遇到的99%SQL优化,这里都能给你解决方案(二)
-- 示例表
CREATE TABLE `employees` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(24) NOT NULL DEFAULT '' COMMENT '姓名',
`age` int(20) NOT NULL DEFAULT '0' COMMENT '年龄',
`position` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',
`hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '入职时间',
PRIMARY KEY (`id`),
KEY `idx_name_age_position` (`name`,`age`,`position`) USING BTREE,
KEY `idx_age` (`age`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=136326 DEFAULT CHARSET=utf8 COMMENT='员工表'
Order by与Group by优化
EXPLAIN select * from employees WHERE name='LiLei' and position='dev' order by age;

利用最左前缀法则:中间字段不能断,因此查询用到了name索引,从key_len=74也能看出,age索引列用在排序的过程中,因为Extra字段里没有using filesort。
EXPLAIN select * from employees WHERE name='LiLei' order by position;

从explain的执行结果来看:key_len=74, 查询使用name索引,由于用了position进行排序,跳过了age,出现了Using filesort。
EXPLAIN select * from employees WHERE name='LiLei' order by age,position;

查找只用到了name索引,age和position用于排序,无Using filesort。
EXPLAIN select * from employees WHERE name='LiLei' order by position,age;

和上一个case不同的是,Extra中出现了Using filesort,因为索引的创建顺序为name,age,position,但是排序的时候age和position颠倒了位置。
EXPLAIN select * from employees WHERE name='LiLei' order by age asc, position desc;

虽然排序的字段和联合索引顺序是一样的,且order by是默认升序,这里position desc是降序,导致与索引的排序方式不同,从而产生Using filesort。Mysql8以上版本有降序索引可以支持该种查询方式。
EXPLAIN select * from employees WHERE name in('LiLei', 'zhuge') order by age, position ;

对于排序来说,多个相等条件也是范围查询。
EXPLAIN select * from employees WHERE name > 'a' order by name;

可以用覆盖索引优化
EXPLAIN select name,age,position from employees WHERE name > 'a' order by name;

filesort排序
EXPLAIN select * from employees where name='LiLei' order by position;

查看这条sql对应trace结果(只展示排序部分):
set session optimizer_trace="enabled=on",end_markers_in_json=on; ‐‐开启trace
select * from employees where name = 'LiLei' order by position;
select * from information_schema.OPTIMIZER_TRACE;
{
"join_execution": { --sql执行阶段
"select#": 1,
"steps": [
{
"filesort_information": [
{
"direction": "asc",
"table": "`employees`",
"field": "position"
}
] /* filesort_information */,
"filesort_priority_queue_optimization": {
"usable": false,
"cause": "not applicable (no LIMIT)"
} /* filesort_priority_queue_optimization */,
"filesort_execution": [
] /* filesort_execution */,
"filesort_summary": { --文件排序信息
"rows": 1, --预计扫描行数
"examined_rows": 1, --参与排序的行
"number_of_tmp_files": 0, --使用临时文件的个数,这个值为0代表全部使用sort_buffer内存排序,否则使用磁盘文件排序
"sort_buffer_size": 200704, --排序缓存的大小
"sort_mode": "<sort_key, additional_fields>" --排序方式,这里用的单路排序
} /* filesort_summary */
}
] /* steps */
} /* join_execution */
}
修改max_length_for_sort_data=10
set max_length_for_sort_data = 10; --employees表所有字段长度总和肯定大于10字节
select * from employees where name = 'LiLei' order by position;
select * from information_schema.OPTIMIZER_TRACE;
{
"join_execution": {
"select#": 1,
"steps": [
{
"filesort_information": [
{
"direction": "asc",
"table": "`employees`",
"field": "position"
}
] /* filesort_information */,
"filesort_priority_queue_optimization": {
"usable": false,
"cause": "not applicable (no LIMIT)"
} /* filesort_priority_queue_optimization */,
"filesort_execution": [
] /* filesort_execution */,
"filesort_summary": {
"rows": 1,
"examined_rows": 1,
"number_of_tmp_files": 0,
"sort_buffer_size": 53248,
"sort_mode": "<sort_key, rowid>" --排序方式为双路排序
} /* filesort_summary */
}
] /* steps */
} /* join_execution */
}
对比这两个排序模式,单路排序会把所有的需要查询的字段数据都放到sort_buffer中,而双路排序只会把主键id和需要排序的字段放到sort_buffer中进行排序,然后再通过主键id 回到原表 查询需要的字段数据。MySQL通过max_length_for_sort_data这个参数来控制排序,在不同场景下使用不同的排序模式,从而提升排序效率。
优化总结
- Mysql支持两种方式的排序filesort和index,using index是指Mysql扫描索引本身完成排序。index效率高,filesort效率低。
- order by满足两种情况会使用using index。
order by语句使用索引最左前列。
使用where子句和order by子句 条件列组合满足索引最左前列。 - 尽量在索引列上完成排序,遵循索引建立(索引创建的顺序)时候的最左前缀法则。
- 如果order by 的条件不在索引列上,就会产生using filesort。
还没关注我的公众号?
- 扫文末二维码关注公众号【小强的进阶之路】可领取如下:
- 学习资料: 1T视频教程:涵盖Javaweb前后端教学视频、机器学习/人工智能教学视频、Linux系统教程视频、雅思考试视频教程;
- 100多本书:包含C/C++、Java、Python三门编程语言的经典必看图书、LeetCode题解大全;
- 软件工具:几乎包括你在编程道路上的可能会用到的大部分软件;
- 项目源码:20个JavaWeb项目源码。

工作中遇到的99%SQL优化,这里都能给你解决方案(二)的更多相关文章
- 工作中遇到的99%SQL优化,这里都能给你解决方案
前几篇文章介绍了mysql的底层数据结构和mysql优化的神器explain.后台有些朋友说小强只介绍概念,平时使用还是一脸懵,强烈要求小强来一篇实战sql优化,经过周末两天的整理和总结,sql优化实 ...
- 工作中遇到的99%SQL优化,这里都能给你解决方案(三)
-- 示例表 CREATE TABLE `employees` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(24) NOT NULL ...
- 收集一些工作中常用的经典SQL语句
作为一枚程序员来说和数据库打交道是不可避免的,现收集一下工作中常用的SQL语句,希望能给大家带来一些帮助,当然不全面,欢迎补充! 1.执行插入语句,获取自动生成的递增的ID值 INSERT INTO ...
- 在工作中常用到的SQL
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 最近在公司做了几张报表,还记得刚开始要做报表的时候都 ...
- 工作中常用到的sql命令!!!
一.mysql数据库日常操作. 1.启动mysql:/etc/init.d/mysql start (前面为mysql的安装路径) 2.重启mysql: /etc/init.d/my ...
- 工作中遇到的一道SQL应用题
登录日志表 CREATE TABLE [dbo].[LoginLog]([Seq] [int] NOT NULL IDENTITY(1, 1), --Seq[UserId] [varchar] (2 ...
- 分享一个工作中遇得到的sql(按每天每人统计拖车次数与小修次数)
查询每人每天的数据 首先先建表 CREATE TABLE `user` ( `name` ) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CR ...
- 《高性能SQL调优精要与案例解析》一书谈SQL调优(SQL TUNING或SQL优化)学习
<高性能SQL调优精要与案例解析>一书上市发售以来,很多热心读者就该书内容及一些具体问题提出了疑问,因读者众多外加本人日常工作的繁忙 ,在这里就SQL调优学习进行讨论并对热点问题统一作答. ...
- Oracle SQl优化总结
对数据库技术的热爱是我唯一的安慰,毕竟这是自己喜欢的事情,还可以做下去. 因为客户项目的需要,我又开始接触Oracle,大部分工作在工作流的优化和业务数据的排查上.为了更好的做这份工作,我有参考过or ...
随机推荐
- 通过wireshark学习Traceroute命令和mtr(UDP,ICMP协议)
traceroute: 通过TTL限定的ICMP/UDP/TCP侦测包来发现从本地主机到远端目标主机之间的第三层转发路径.用来调试网络连接性和路由问题. mtr: traceroute的一个变种,能根 ...
- postman 测试http,接口
1.form-data: 就是http请求中的multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开.既可以上传键值对,也可以上传文件.当上传的字段是文件时 ...
- 直击--vue项目微信小程序页面跳转web-view不刷新-根源
背景 最近项目需要适配小程序,项目是使用了vue开发的网站,其中改造方式是,每个页面都使用小程序创建一个页面通过web-view来显示指定页面的. 在没有使用小程序时,路由跳转时,刷新页面等等,这个是 ...
- Linux安装nfs共享文件
简介nfs nfs网络文件系统常用于共享音视频,图片等静态资源.将需要共享的资源放到NFS里的共享目录,通过服务器挂载实现访问. 服务端安装: yum install -y nfs-utils rpc ...
- 再次学习Git版本控制工具
Git 究竟是怎样的一个系统呢?为什么在SVN作为版本控制工具已经非常流行的时候,还有Git这样一个版本控制工具呢?Git和SVN的区别在哪儿呢?Git优势又在哪呢?下面PHP程序员雷雪松带你一起详细 ...
- EOS源码分析:transaction的一生
最近在处理智能合约的事务上链问题,发现其中仍旧有知识盲点.原有的认识是一个事务请求会从客户端设备打包签名,然后通过RPC传到非出块节点,广播给超级节点,校验打包到可逆区块,共识确认最后变为不可逆区块. ...
- python 编码报错问题 'ascii' codec can't encode characters 解决方法
python在安装时,默认的编码是ascii, 当程序中出现非ascii编码时,python的处理常常会报这样的错 'ascii' codec can't encode characters pyth ...
- 【原创】关于DNS不得不说的一些事
引言 今天我们来聊聊DNS. 所谓域名系统(Domain Name System缩写DNS,Domain Name被译为域名)是因特网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据 ...
- 前端利器躬行记(2)——Babel
Babel是一个JavaScript编译器,不仅能将当前运行环境不支持的JavaScript语法(例如ES6.ES7等)编译成向下兼容的可用语法(例如ES3或ES5),这其中会涉及新语法的转换和缺失特 ...
- 图表控件业界革命 -Arction新产品LightningChart JS 上市
芬兰高科技企业Arction Ltd 在今年8月份推出了用于网页的数据可视化控件新解决方案—— LightningChart JS. 初次的基准测试表明,该产品为网页应用程序的数据可视化刷新了新的纪录 ...