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

一、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. Python 开发工具链全解

    可能刚开始学习Python时,有人跟你说可以将源文件所在的文件夹添加到 PYTHONPATH环境变量中,然后可以从其他位置导入此代码.在大多数情况下,这个人常常忘记补充这是一个非常糟糕的主意.有些人在 ...

  2. 15分钟从零开始搭建支持10w+用户的生产环境(三)

    上一篇文章介绍了这个架构中,选择MongoDB做为数据库的原因,及相关的安装操作. 原文地址:15分钟从零开始搭建支持10w+用户的生产环境(二)   三.WebServer 在SOA和gRPC大行其 ...

  3. 编程语言千千万,为什么学习Python的占一半?

    如果让你从数百种的编程语言中选择一个入门语言?你会选择哪一个? 是应用率最高.长期霸占排行榜的常青藤 Java?是易于上手,难以精通的 C?还是在游戏和工具领域仍占主流地位的 C++?亦或是占据 Wi ...

  4. 从零开始装CentOS以及配置Redis,前端都可以!!!

    ##### 从零开始装CentOS以及配置Redis 1.新建虚拟机 --- ![image](https://img2018.cnblogs.com/blog/1334966/201910/1334 ...

  5. 小程序里button边框有黑线解决办法(自定义button样式)

    .go_to_user::after{ border:1px solid transparent; } button的class为go_to_user button{ padding:; box-si ...

  6. linux find string in files

    http://blog.csdn.net/duguduchong/article/details/7716908 查找目录下的所有文件中是否含有某个字符串 find .|xargs grep -ri ...

  7. hdu_2124 Flying to the Mars & hdu_1800 Repair the Wall 贪心水题

    hdu_1800 简单排一下序,从大开始把比他小的都访问一遍,ans++: #include <iostream> #include <stdio.h> #include &l ...

  8. http 之 CORS简介

    什么是CORS? CORS:跨域资源共享.是一种机制. 用处? 它使用额外的 HTTP 头来告诉浏览器  让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定 ...

  9. CYQ.Data 轻量数据层之路 使用篇-MProc 存储过程与SQL 视频[最后一集] H (二十八)

    2019独角兽企业重金招聘Python工程师标准>>> 说明: 本次录制主要为使用篇:CYQ.Data 轻量数据层之路 使用篇五曲 MProc 存储过程与SQL(十六)   的附加视 ...

  10. ajax学习摘抄笔记

    2019独角兽企业重金招聘Python工程师标准>>> AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). A ...