衍生表的优化:合并 | 具化

一、mysql优化器对于衍生表的优化处理可以从两方面进行:

  • 将衍生表合并到外部查询

  • 将衍生表具化为内部临时表

1、示例 1:

SELECT * FROM (SELECT * FROM t1) AS derived_t1;

衍生表 derived_t1 合并处理后,实际执行的查询类似如下:

SELECT * FROM t1;

2、示例 2:

SELECT *
FROM t1 JOIN (SELECT t2.f1 FROM t2) AS derived_t2 ON t1.f2=derived_t2.f1
WHERE t1.f1 > 0;

衍生表 derived_t2 合并处理后,实际执行的查询类似如下:

SELECT t1.*, t2.f1
FROM t1 JOIN t2 ON t1.f2=t2.f1
WHERE t1.f1 > 0;

如果是具化操作的话, derived_t1 和 derived_t2 会被作为独立的表来进行查询。

mysql 优化器会尽量避免去具化衍生表。

如果合并操作是的外部表超过61个,则优化器会选择具化表。

二、优化器关于衍生表中 order by 的处理:

1、在 sql 满足如下全部条件时,衍生表的 order by 会被放到外部查询延迟执行,反之,则会被忽略:

  • 外部查询无分组、聚合操作。

  • 外部查询没有使用 DISTINCTHAVING 或 ORDER BY等操作。

  • 外部查询只有衍生表这个唯一的查询源。

2、可以通过以下几种方式进行优化器的衍生表合并:

  • 关闭 derived_merge:mysql5.7默认是开启的。

  • 子查询使用一些特定操作来组织优化器合并操作:

    • 集合函数 (SUM()MIN()MAX()COUNT()等等)

    • DISTINCT

    • GROUP BY

    • HAVING

    • LIMIT

    • UNION 或者 UNION ALL

    • Subqueries in the select list

    • Assignments to user variables

    • Refererences only to literal values (in this case, there is no underlying table)

三、实际应用

笔者曾经遇到需要查询关联同一身份证信息的所有用户中最新关联的用户记录:

SELECT id, name, created_at FROM(
SELECT table1.*, max(table1.created_at) FROM(
SELECT * FROM users ORDER BY created_at desc
) table1 GROUP BY id_no
) table2
ORDER BY id

但是,并没有得到想要的结果,查看执行计划如下:

只有一个衍生表,但是,看我们的sql,明明有三层查询。

想到之前,mysql版本做过升级,当前为5.7版本,考虑到mysql5.7版本对于衍生表的优化处理,首先能够确定的一点是优化器对衍生表做了合并处理,但是仅仅是合并,也不应该影响预期的查询结果。

参考第二节中介绍的,进一步观察可知,最内部的 SELECT * FROM users ORDER BY created_at desc 不满足第二.2中的条件,因此 order by 丢失导致查询结果不符合预期。

sql调整:确定记录不超过10000,所以添加 limit 1000 来阻止优化器对衍生表进行合并操作

SELECT id, name, created_at FROM(
SELECT table1.*, max(table1.created_at) FROM(
SELECT * FROM users ORDER BY created_at desc LIMIT
) table1 GROUP BY id_no
) table2
ORDER BY id

查看执行计划如下:

两层衍生表,符合sql预期,执行结果也符合预期。

或者,也可以执行如下调整:使用 HAVING 1=1 等true条件

SELECT id, name, created_at FROM(
SELECT table1.*, max(table1.created_at) FROM(
SELECT * FROM users HAVING = ORDER BY created_at desc
) table1 GROUP BY id_no
) table2
ORDER BY id

查看执行计划如下:

同样阻止了优化器的衍生表合并操作。

mysql5.7 derived_merge=on 影响你的查询了吗?的更多相关文章

  1. 经验:什么影响了数据库查询速度、什么影响了MySQL性能 (转)

    一.什么影响了数据库查询速度 1.1 影响数据库查询速度的四个因素 1.2 风险分析 QPS:Queries Per Second意思是“每秒查询率”,是一台服务器每秒能够相应的查询次数,是对一个特定 ...

  2. 使用mysql5.7新特性解决前通配符查询性能问题

    众所周知,在mysql里的后通配符可以使用索引查找,前通配查询却无法使用到索引,即使是使用到了索引,也是使用了索引全扫描,效率依然不高,再MySQL5.7之前,一直都没有好的办法解决,但是到了MySQ ...

  3. 高性能MySQL笔记 第6章 查询性能优化

    6.1 为什么查询速度会慢   查询的生命周期大致可按照顺序来看:从客户端,到服务器,然后在服务器上进行解析,生成执行计划,执行,并返回结果给客户端.其中“执行”可以认为是整个生命周期中最重要的阶段. ...

  4. 慢查询日志(mysql)

    参考 针对mysql的优化,mysql提供了慢查询日志的支持.mysql的慢查询是mysql提供的一种日志记录,它用来记录mysql中响应时间超过阀值的sql语句,某个sql运行时间如果超过设置的阀值 ...

  5. 分分钟解决MySQL查询速度慢与性能差

    阅读本文大概需要 6 分钟. 一.什么影响了数据库查询速度 1.1 影响数据库查询速度的四个因素 1.2 风险分析 QPS: QueriesPerSecond意思是“每秒查询率”,是一台服务器每秒能够 ...

  6. percona-xtrabackup工具实现mysql5.6.34的主从同步复制

    percona-xtrabackup工具实现mysql5.6.34的主从同步复制 下载并安装percona-xtrabackup工具 # wget https://www.percona.com/do ...

  7. mysql5.7 安装和多源复制实践

    MySQL 5.7发布后,在复制方面有了很大的改进和提升.比如开始支持多源复制(multi-source)以及真正的支持多线程复制了.多源复制可以使用基于二进制日子的复制或者基于事务的复制.下面我们说 ...

  8. 关闭mysql慢查询日志

    开启mysql慢日志 MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查 ...

  9. 分分钟解决 MySQL 查询速度慢与性能差

    一.什么影响了数据库查询速度 1.1 影响数据库查询速度的四个因素 1.2 风险分析 QPS: QueriesPerSecond意思是“每秒查询率”,是一台服务器每秒能够相应的查询次数,是对一个特定的 ...

随机推荐

  1. 图解AVL树

    1:AVL树简介 二叉搜索树在一般情况下其搜索的时间复杂度为O(logn),但某些特殊情况下会退化为链表,导致树的高度变大且搜索的时间复杂度变为O(n),发挥不出树这种数据结构的优势,因此平衡二叉树便 ...

  2. blink测试技术介绍

    引言: flink是面向数据流处理和批处理的分布式开源计算框架.2016年阿里巴巴引入flink框架,改造为blink,将其运用到搜索及推荐的离线实时计算中,成功解决了搜索.推荐实时大数据量计算的痛点 ...

  3. TIME_WAIT的危害与避免

    time-wait的产生: 在TCP连接中四次挥手关闭连接时,主动关闭连接的一方(上图中时Client)会在发送最后一条ACK报文后维持一段时长2MSL(MSL指的是数据包在网络中的最大生存时间)的等 ...

  4. Docker镜像与仓库(四)

    Dockerfile方式创建镜像 https://hub.docker.com/_/centos/ #找一个centos6.6 的dockerfile链接 [root@linux-node1 ~]# ...

  5. Redis持久化存储(三)

    redis高级特性-发布订阅消息服务功能 Pub/Sub 订阅,取消订阅和发布实现了发布/订阅消息范式(引自wikipedia),发送者(发布者)不是计划发送消息给特定的接收者(订阅者).而是发布的消 ...

  6. css之Grid Layout详解

    css之Grid Layout详解 CSS Grid Layout擅长将页面划分为主要区域,或者在从HTML基元构建的控件的各个部分之间定义大小,位置和图层之间的关系. 与表格一样,网格布局使作者能够 ...

  7. UVA10599:Robots(II)(最长上升子序列)

    Your company provides robots that can be used to pick up litter from fields after sporting events an ...

  8. Netflix:当你按下“播放”的时候发生了什么?

    从用户端来看,使用Netflix是很简单的,按下播放键之后视频就像变魔术一样完美呈现了.看起来很容易是吧?然而实际不是这样的.了解过云计算的人可能会简单地以为,既然Netflix使用AWS来提供视频服 ...

  9. #if 和#ifdef的区别

    转自:https://blog.csdn.net/zhangchiytu/article/details/7563329 先看个例子:#define TARGET_LITTLE_ENDINA 1#de ...

  10. C++获取当前系统时间并格式化输出

    C++中与系统时间相关的函数定义在头文件中. 一.time(time_t * )函数 函数定义如下: time_t time (time_t* timer); 获取系统当前日历时间 UTC 1970- ...