MySQL · 性能优化 · 条件下推到物化表
MySQL · 性能优化 · 条件下推到物化表
http://mysql.taobao.org/monthly/2016/07/08/
背景
MySQL引入了Materialization(物化)这一关键特性用于子查询(比如在IN/NOT IN子查询以及 FROM 子查询)优化。
具体实现方式是:在SQL执行过程中,第一次需要子查询结果时执行子查询并将子查询的结果保存为临时表 ,后续对子查询结果集的访问将直接通过临时表获得。
与此同时,优化器还具有延迟物化子查询的能力,先通过其它条件判断子查询是否真的需要执行。物化子查询优化SQL执行的关键点在于对子查询只需要执行一次。 与之相对的执行方式是对外表的每一行都对子查询进行调用,其执行计划中的查询类型为“DEPENDENT SUBQUERY”。
在使用Materialization(物化)能提高SQL性能的同时,也有必要留意相关SQL是否存在进一步优化空间的可能性。比如下面描述的场景:
mysql>explain extended Select * from (select * from score where score >= 60) derived1 where class_id = 10;
+----+-------------+------------+-------+---------------+-------------+---------+-------+------+----------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+-------+---------------+-------------+---------+-------+------+----------+--------------------------+
| 1 | PRIMARY | <derived2> | ref | <auto_key0> | <auto_key0> | 4 | const | 0 | 100 | |
| 2 | DERIVED | score | index | idx_score | idx_score | 4 | | 1 | 100 | Using where; Using index |
+----+-------------+------------+-------+---------------+-------------+---------+-------+------+----------+--------------------------+
从执行计划可看出,MySQL首先物化了子查询(select_type=DERIVED,或者以format=json格式查看执行计划),然后再通过class_id字段对结果集进行过滤。这个SQL从语义上,也可以写成如下形式,若索引合理执行效率会更高。
select * from score where score >= 60 and class_id=10
从这个例子可以看出子查询物化时的一个潜在问题:当子查询本身比较耗费资源或结果集较大时,往往存在较高的优化空间,特别是在外层条件可作用于子查询的情况下。通过条件下推,在执行过程中尽早减少数据访问量,能显著提高性能。本文重点描述将条件下推到物化子查询的场景。
分析
事实上前面提到的查询在5.7版本可以自动重写。打开优化器选项 derived_merge=on 后,查看重写后的语句如下:
select `remall`.`score`.`class_id` AS `class_id`,`remall`.`score`.`student_id` AS `student_id`,`remall`.`score`.`score` AS `score`
from `remall`.`score`
where ((`remall`.`score`.`class_id` = 10) and (`remall`.`score`.`score` >= 60))
另一方面,并不是所有子查询可以做到自动条件下推。比如下面这个语句:
select * from (select class_id, avg(score) from score group by class_id) derived1 where class_id = 10;
出现这种现象的原因是MySQL优化器目前只能对Mergable的视图或子查询进行重写。理解这一概念可以先从视图的两种算法入手:merge 和 temptable。
一般较为复杂的视图或子查询会使用temptable算法类型,包括:
1. 聚合子查询;
2. 含有LIMIT的子查询;
3. UNION 或UNION ALL子查询;
4. 输出字段中的子查询;
我们也可以显示的通过创建视图来判断子查询是否使用了merge算法。 比如:
mysql>create algorithm=merge view v as select class_id, avg(score) from score group by class_id;
执行成功,花费 2.46 ms.
mysql>show warnings;
+---------+------+-------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+-------------------------------------------------------------------------------+
| Warning | 1354 | View merge algorithm can't be used here for now (assumed undefined algorithm) |
+---------+------+-------------------------------------------------------------------------------+
我们创建视图时指定使用merge,但是数据库判定该算法不适合因此使用默认的undefined(实际执行过程中使用temptable算法)。
/**
Strategy for how to process a view or derived table (merge or materialization)
*/
enum enum_view_algorithm {
VIEW_ALGORITHM_UNDEFINED = 0,
VIEW_ALGORITHM_TEMPTABLE = 1,
VIEW_ALGORITHM_MERGE = 2
};
使用merge算法的视图或子查询能够将查询条件下推到视图或子查询内部;而temptable算法子查询或视图不能将条件下推,只能在结果集上做进一步过滤。优化器对对这一判断标准为:
bool merge_derived(THD *thd, TABLE_LIST *derived_table)
{
...
// Check whether derived table is mergeable, and directives allow merging
if (!derived_unit->is_mergeable() ||
derived_table->algorithm == VIEW_ALGORITHM_TEMPTABLE ||
(!thd->optimizer_switch_flag(OPTIMIZER_SWITCH_DERIVED_MERGE) &&
derived_table->algorithm != VIEW_ALGORITHM_MERGE))
DBUG_RETURN(false);
...
}
条件下推原则
不是所有数据库引擎都完美实现条件下推下推到子查询的功能。对MySQL中使用聚合查询的视图或者from子查询,建议的条件下推原则是:
查询中只依赖于视图或者from子查询输出字段的where 条件能够安全的下推。
同时需要注意条件下推到视图或derived table子查询后所存放的恰当位置:
- 从语义上看,下推到聚合子查询的条件可以放在 HAVING 子句里。下推后的 HAVING字句可以是: HAVING xxx and NEW_CONDITION operation VALUE;
- 若条件是子查询的group 字段,且该条件上有索引,那么将该条件放在子查询的where字句中,性能会更好(HAVING条件中不含聚合函数时,将该条件下推到where字句中过滤整个group)。
对于其他类型的视图或from子查询,也可以通过语义检查的方式进行人工条件下推。
总结
任何数据库的优化器都不是万能的。 了解优化器的特性后并规避其短处,才能写出最优SQL语句。
MySQL · 性能优化 · 条件下推到物化表的更多相关文章
- MySQL · 性能优化 · MySQL常见SQL错误用法(转自-阿里云云栖社区)
作者:阿里云云栖社区链接:https://zhuanlan.zhihu.com/p/26043916来源:知乎著作权归作者所有,转载请联系作者获得授权. 前言 MySQL在2016年仍然保持强劲的数据 ...
- Mysql性能优化三(分表、增量备份、还原)
接上篇Mysql性能优化二 对表进行水平划分 如果一个表的记录数太多了,比如上千万条,而且需要经常检索,那么我们就有必要化整为零了.如果我拆成100个表,那么每个表只有10万条记录.当然这需要数据在逻 ...
- MySQL 性能优化系列之一 单表预处理
MySQL 性能优化系列之一 单表预处理 背景介绍 我们经常在写多表关联的SQL时,会想到 left jion(左关联),right jion(右关联),inner jion(内关联)等. 但是,当表 ...
- MySQL性能优化(五):分表
原文:MySQL性能优化(五):分表 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/vbi ...
- 涨姿势:Mysql 性能优化完全手册
涨姿势:Mysql 性能优化完全手册 深入理解MySQL服务器架构 客户端层 MySQL逻辑架构整体分为三层,最上层为客户端层,诸如:连接处理.授权认证.安全等功能均在这一层处理. 中间层 MySQL ...
- [MySQL性能优化系列]巧用索引
1. 普通青年的索引使用方式 假设我们有一个用户表 tb_user,内容如下: name age sex jack 22 男 rose 21 女 tom 20 男 ... ... ... 执行SQL语 ...
- MySQL性能优化:索引
MySQL性能优化:索引 索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序.数据库使用索引以找到特定值,然后顺指针找到包含该值的行.这样可以使对应于表的SQL语句执 ...
- MySQL性能优化总结
一.MySQL的主要适用场景 1.Web网站系统 2.日志记录系统 3.数据仓库系统 4.嵌入式系统 二.MySQL架构图: 三.MySQL存储引擎概述 1)MyISAM存储引擎 MyISAM存储引擎 ...
- MYSQL性能优化的最佳20+条经验
MYSQL性能优化的最佳20+条经验 2009年11月27日 陈皓 评论 148 条评论 131,702 人阅读 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数 ...
随机推荐
- Html - 仿Ios assistiveTouch 悬浮辅助球工具
仿Ios assistiveTouch 悬浮辅助球工具 <!DOCTYPE html> <html> <head> <meta charset="u ...
- Css3 - 动画旋转
旋转1: <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="U ...
- 【液晶模块系列基础视频】3.4fatfs接口函数的使用4
============================= 技术论坛:http://www.eeschool.org 博客地址:http://xiaomagee.cnblogs.com 官方网店:ht ...
- ASP.NET MVC4系列验证机制、伙伴类共享源数据信息(数据注解和验证)
一,mvc前后台验证 自定义属性标签MyRegularExpression using System; using System.Collections.Generic; using System.C ...
- sqlite相关工具使用
sqlite3可视化工具 1.sudo apt-get install sqlitebrowser 2.sudo apt-get install sqliteman3.sqlitestudio需要去官 ...
- POJ 2299 树状数组+离散化求逆序对
给出一个序列 相邻的两个数可以进行交换 问最少交换多少次可以让他变成递增序列 每个数都是独一无二的 其实就是问冒泡往后 最多多少次 但是按普通冒泡记录次数一定会超时 冒泡记录次数的本质是每个数的逆序数 ...
- 资源(1)----封装类(连接数据库mysql,分页)
一,链接MYSQL数据库 class DBDA{ public $host="localhost";//服务器地址 public $uid="root";//数 ...
- 初步理解Java的三大特性——封装、继承和多态
声明:整理自网络,如有雷同,请联系博主处理 一.封装 封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被 ...
- 会php不回缓存行吗?多重实现
1.普遍缓存技术: 数据缓存:这里所说的数据缓存是指数据库查询PHP缓存机制,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据,并把查询结果序列化后保存到文件中 ...
- Two's complement
https://en.wikipedia.org/wiki/Two's_complement The two's-complement system has the advantage that th ...