Mysql优化(出自官方文档) - 第四篇
目录
- Mysql优化(出自官方文档) - 第四篇
- 1 Condition Filtering
- 2 Constant-Folding Optimization
- 3 ORDER BY Optimization
Mysql优化(出自官方文档) - 第四篇
1 Condition Filtering
在join
中,prefix rows
指从一个table
中扫描出来的传递给下一个表的行,为了防止传递的行增长的过快,有时候,优化器会尝试提前对prefix rows
进行过滤(比如将where
中的条件提前等)。
有助于进行此操作的条件需要符合如下场景:
- 该过滤条件作用的对象是当前表
- 依赖于
join
序列中前面表的值(常量或者普通的值) - 不会因为
access method
(这里指join
)而导致结果改变。
在EXPLAIN
的输出结果里面,rows
列表示优化器为access method
预估的行数,filtered
列表示condition filtering
所带来的效果,其值为一个百分比,100%表示没有列被过滤,随之递减,表示过滤的效果。
优化器为prefix rows
预估的量(称为prefix rows count
)即为rows
列乘以filtered
。
来看一个例子:
SELECT *FROM employee JOIN department ON employee.dept_no = department.dept_noWHERE employee.first_name = 'John'AND employee.hire_date BETWEEN '2018-01-01' AND '2018-06-01';
假设这两个表信息如下:
employee
有1024行,department
有12行- 两张表在
dept_no
列上都有索引,且employee
表在first_name
也有索引 employee
中有8行满足employee.first_name = 'John'
employee
有150行满足employee.hire_date BETWEEN '2018-01-01' AND '2018-06-01'
employee
中只有1行满足employee.first_name = 'John' AND employee.hire_date BETWEEN '2018-01-01' AND '2018-06-01';
如果没有condition filtering
,那么EXPLAIN
的输出结果如下:
+----+------------+--------+------------------+---------+---------+------+----------+
| id | table | type | possible_keys | key | ref | rows | filtered |
+----+------------+--------+------------------+---------+---------+------+----------+
| 1 | employee | ref | name,h_date,dept | name | const | 8 | 100.00 |
| 1 | department | eq_ref | PRIMARY | PRIMARY | dept_no | 1 | 100.00 |
+----+------------+--------+------------------+---------+---------+------+----------+
可以看到,在employee
中符合employee.first_name = 'John'
的有8行,因此没有filtering被应用,此时的prefix row count
为8 * 100% = 8
当应用condition filtering
的时候,优化器就会应用where
语句中没有被access method
(此处为join
)所采用的过滤条件,在这个例子里面,这个条件是BETWEEN
语句,因此,此时EXPLAIN
的输出结果为:
+----+------------+--------+------------------+---------+---------+------+----------+
| id | table | type | possible_keys | key | ref | rows | filtered |
+----+------------+--------+------------------+---------+---------+------+----------+
| 1 | employee | ref | name,h_date,dept | name | const | 8 | 16.31 |
| 1 | department | eq_ref | PRIMARY | PRIMARY | dept_no | 1 | 100.00 |
+----+------------+--------+------------------+---------+---------+------+----------+
此时的prefix rows count
为8 * 16.31% = 1.3
,已经很接近实际的数据量了,此时传给department
的数据量已经只有一行了。
通常来讲,优化器不会为最后一个表进行condition filtering
预估,因为最后一张表已经不会把数据往下传了,因此,没有必要这样做。
下面的做法会有助于优化器使用这项技术:
如果某一列没有加索引,那么对其创建索引,这样子优化器就可以有足够的信息对其进行row estimates
类似的,如果某一列没有直方图,那么生成一个
修改join顺序
禁止对session的condition filtering:
SET optimizer_switch = 'condition_fanout_filter=off';
或者使用Mysql的hint功能:
SELECT /*+ SET_VAR(optimizer_switch = 'condition_fanout_filter=off') */ ...
2 Constant-Folding Optimization
在平时的使用过程中,如果用户在where
语句中进行范围判断,判断的常量值超过列类型的范围,那么,此时where
条件将会被折叠,比如下面的例子:
CREATE TABLE t (c TINYINT UNSIGNED NOT NULL);
如果用户使用如下的查询语句:
SELECT * FROM t WHERE c < 256
由于c的类型为TINYINT UNSIGNED
,那么它的最大值就会255,此时,Mysql会把where
条件优化为where 1
,相应的,如果在定义c
的时候没有NOT NULL
,那么where
条件会被优化为 where c IS NOT NULL.
相应的,Mysql在处理浮点型的时候,也会做对应的处理,如果用户指定的常量值超过了精度范围,那么会做适当的裁剪。
3 ORDER BY Optimization
在进行order by
操作时,Mysql主要使用两种方式来进行排序,如果索引可以使用,那么直接使用索引自身的排序,如果不能,则使用filesort
来进行排序。
Use of Indexes to Satisfy ORDER BY
当用户进行查询的时候,如果查询的列多于
order by
的列(order by
的列有索引),那么此时也不一定会使用索引进行排序,因为用户选择的列多于索引列,Mysql就需要通过索引去盘上读其他列,此时带来的开销有可能会大于直接扫描表在进行filesort
的开销。下面的例子,Mysql均有可能会使用索引来进行排序:
- 示例1:
SELECT pk, key_part1, key_part2 FROM t1ORDER BY key_part1, key_part2;
key_part1
和key_part2
均建有索引,并且查询的结果也全都为索引,在Innodb
中,primary key
默认为索引的一部分。- 示例2:
SELECT * FROM t1ORDER BY key_part1 DESC, key_part2 DESC;SELECT * FROM t1WHERE key_part1 = constantORDER BY key_part2 DESC;
key_part1
等于一个constant
,相当于当前的排序完全靠key_part2
来决定,此时Mysql也可能使用索引来进行排序。- 示例3:
SELECT * FROM t1ORDER BY key_part1 DESC, key_part2 ASC;
即使两个相反,也有可能使用索引来进行排序。
- 示例4:
SELECT * FROM t1WHERE key_part1 > constantORDER BY key_part1 ASC;SELECT * FROM t1WHERE key_part1 < constantORDER BY key_part1 DESC;
只要是和常量进行比较,就有可能使用索引来进行排序。
下面的例子,即使
order by
使用了索引,但是Mysql也没办法使用索引来排序order by
使用了不同的索引:SELECT * FROM t1 ORDER BY key1, key2;
key1,key2
指两个不同的索引,而并非一个索引的两个部分。order by的对象是非连续的索引:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1_part1, key1_part3;
用来获取rows的索引不同于order by中的索引:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
order by的对象虽然是索引,但是不是索引列,而是一个针对于索引的表达式:
SELECT * FROM t1 ORDER BY ABS(key); SELECT * FROM t1 ORDER BY -key;
join
了很多个table
,但是order by
的列并不是完全来自于第一个非const table
。order by
的对象和group by
的对象不一样。只索引了列的一部分,比如
char(20)
,结果只索引了前10个字节,那么此时也没办法使用索引来进行排序。索引没有按照顺序来存储,比如
HASH INDEX
在Mysql5.7或者之前的版本里,
group by
在特定条件下会包含默认的排序动作,所以需要在末尾加上order by NULL
来避免这种排序动作,但是在Mysql8.0往后,则不再需要这样的写法,这种默认的排序动作已经被取消,同样的,产生的结果顺序也将和以前的版本会有些不同,为了保证顺序,请加上order by
这样的语句。Use of filesort to Satisfy ORDER BY
在Mysql8.0.12之前,
sort_buffer_size
参数会分配一个固定的大小的内存来进行filesort操作,在8.0.12之后,这种方式被优化为根据需求增量的使用内存,这样子可以更高效的利用内存,从而尽可能避免的使用临时文件来进行排序。Influencing ORDER BY Optimization
对于那些没有使用filesort的排序,试着减小
max_length_for_sort_data
环境变量,该值设置过高会导致较高的磁盘读写和较低CPU运算。如果一个排序无法使用索引,尝试使用下面的策略来优化filesort。- 增大
sort_buffer_size
,可以避免更少的磁盘读写和合并操作,同时需要注意的是,如果增加了max_sort_length
,那么同样的也要增加sort_buffer_size
。 - 增加
read_rnd_buffer_size
,这样子可以使得一次读出更多的行数 - 将
tmpdir
系统变量修改到更大的磁盘上,生成的临时文件将会有足够的存储空间
- 增大
ORDER BY Execution Plan Information Available
在
EXPLAIN
的输出里面,对于使用index
排序和filesort
排序分别有以下两种输出:- 如果
Extra
列没有包含Using filesort
,那么使用index
排序 - 如果
Extra
包含Using filesort
,那么使用的filesort
进行的排序。
此外,如果使用的是
filesort
,那么optimizer trace
的输出会有一个filesort_summary
块,举例如下:"filesort_summary": {"rows": 100,"examined_rows": 100,"number_of_tmp_files": 0,"peak_memory_used": 25192,"sort_mode": "<sort_key, packed_additional_fields>" }
部分解释如下:
peak_memory_used
:表示排序过程中使用的最大内存,由于Mysql8.0.12后,filesort
使用的内存是增量增加的,而不再是以前固定好一次性申请,因此,该值就会随着实际情况而变化;sort_mode
解释如下:<sort_key, rowid>
:表示排序是按照sort key
进行的,rowid
用来从表中读取具体的行<sort_key, additional_fields>
:additional_fields
为sql语句需要查询的列,sort key
用来排序,additional_fields
的值直接从表中读取<sort_key, packed_additional_fields>
:和上一个类似,但是additional_fields
是被打包在一起,而非用一种固定长度的编码。
- 如果
转载于:https://www.cnblogs.com/seancheer/p/11250291.html
Mysql优化(出自官方文档) - 第四篇相关推荐
- [WebApp开发]基础教程-Google官方文档-第四篇
文档内容 在Android Browser中使用控制台API 在WebView中使用控制台API 参考 调试 如果你是在为Android开发web应用,那么,你可以使用控制台(console)的Jav ...
- OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)
OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...
- Unity 优化翻译官方文档(二) ------ 平台特定覆盖的纹理压缩格式
官方文档 : https://docs.unity3d.com/Manual/class-TextureImporterOverride.html 虽然Unity支持许多常见的图像格式作为导入纹理的源 ...
- 【goldengate】官方文档笔记四 Oracle GoldenGate实时数据分布
数据分布配置是一对多得配置方案.OGG支持将源库同步到多个目标系统. 数据分布配置需要注意事项: 如果数据传输过程中,投递进程(data pump)发现目标库网络连接出现故障,捕获到得数据会继续像其它 ...
- Unity优化翻译官方文档(六) ------ CPU Usage Profiler
官网地址 : https://docs.unity3d.com/Manual/ProfilerCPU.html CPU使用分析器显示在您的游戏中花费的时间.当它被选中时,下窗格将显示所选帧的分层时间数 ...
- 看懂mysql执行计划--官方文档
原文地址:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html 9.8.2 EXPLAIN Output Format The EXP ...
- storm mysql trident_Apache Storm 官方文档 —— Trident 教程
Trident 是 Storm 的一种高度抽象的实时计算模型,它可以将高吞吐量(每秒百万级)数据输入.有状态的流式处理与低延时的分布式查询无缝结合起来.如果你了解 Pig 或者 Cascading 这 ...
- Android5更新包,Android 5.x OTA Update官方文档(四、OTA更新包解读)
http://blog.csdn.net/huangyabin001/article/details/44873753 写在前面: 写在前面:若能直译,不会意译,意译不成,为了选择不误导他人也会漏译无 ...
- Unity 优化翻译官方文档(三) ------ Animation Clips
动画剪辑是Unity动画中最小的组成部分.它们代表了一个孤立的运动,如RunLeft.跳转或爬行,并且可以以各种方式进行操作和组合,以产生生动的最终结果(参见动画状态机.动画控制器控制器或混合树).您 ...
- 【goldengate】官方文档笔记三 Oracle GoldenGate 实时报表
这篇文档循序渐进的讲述了OGG在适时复制的几种配置方案.从最基本的配置开始讲起,逐渐加入新的进程,加入新的策略,配置也随之改变.下面从最基础的配置说起. 报表配置 一对一复制是OGG最基本的配置方案: ...
最新文章
- NeurIPS 2020中国入选论文:新一代算法“鉴黄师”诞生,中科院计算所研究生一作...
- 8 -- 深入使用Spring -- 5...1 启用Spring缓存
- 数字信号处理学习笔记(五)|有限脉冲响应数字滤波器的设计
- 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目
- AD管控下的弹性云桌面和文件共享最佳实践
- 打破PermGen神话
- python三大结构、顺序结构_Python学习笔记3——三大结构:顺序,分支,循环3
- MySQL——JSON_REPLACE()函数修改JSON属性值
- matlab画无量纲速度分布,麦克斯韦分布与概率论中典型分布的比较教学
- 面向对象设计原则之2-开放闭合原则
- 小狼程序员:工作遐想
- 安装ubuntu后需要做的事
- SAP License:制造企业信息化新动向
- GraphX的三大图算法
- 人口流动趋势matlab,数学建模-人口模型-人口预测
- 让每个生命带着尊严谢幕!淘宝竟有这样一家“临终关怀”网店
- 密码学(期末复习版)
- MAC如何安装pfx
- Java - 传参到底是哪种? pass by value or pass by reference
- 区块链会与io域名有什么关系
热门文章
- 汕尾php培训,系统发生错误
- 拜托!不要用“ ! = null “ 做判空了
- Dubbo 是如何控制并发数和限流的?
- 接口自动化测试框架搭建(9、自动化测试case的编写)--python+HTMLTestRunnerCN+request+unittest+mock+db
- mysql会话杀不掉_SQL Server会话KILL不掉,一直处于KILLED /ROLLBACK状态情形浅析
- mongodb mysql 事务_让你的mongodb支持事务---升级到mongodb 4.0
- 怎么调节手机的刷新率_【W21 5G性能篇】120Hz自适应刷新率,用了再也回不去
- c语言 键盘输入结构体,C语言结构体问题
- 单位阶跃函数的傅里叶变换_傅里叶变换学习笔记(9)
- 华擎 j3455 时钟 linux,经验 篇一:华擎J3455 硬改MAC地址