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

一、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. gridview 合并单元格后,选中颜色重新绘制

    gv_docargo.RowStyle += OnRowStyle; private void OnRowStyle(object sender, DevExpress.XtraGrid.Views. ...

  2. springboot+dubbo简单分布式RPC调用demo

    使用springboot+dubbo搭建RPC入门案例 本文背景简述: 最近在学习公司的一套RPC框架,初步接触的时候感觉挺复杂的.但是知道其原理肯定是和dubbo很相似的,毕竟都是RPC框架嘛,只是 ...

  3. thinkphp--多表查询

    我们可以将两个表连起来一起查询数据,我现在有两张表,一个是feedback表和member表,如图: 总目录: 上代码: $where = array(); $"; $Model = M(' ...

  4. 2019-2020-1 20199328《Linux内核原理与分析》第二周作业

    冯诺依曼体系结构的核心是: 冯诺依曼体系结构五大部分:控制器,运算器,存储器,输入输出设备. 常用的寄存器 AX.BX.CX.DX一般存放一些一般的数据,被称为通用寄存器,分别拥有高8位和低8位. 段 ...

  5. [Qt]执行cmd命令

    要加 /c 参数 QProcess p; p.start("cmd", QStringList()<<"/c"<<"ping ...

  6. 【Linux常见命令】tar命令

    [独立命令,只能用其中一个,和别的命令连用]这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个. -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末 ...

  7. Vue学习—— Vuex学习笔记

    组件是Vue最强大的功能之一,而组件实例的作用域是相互独立的,意味着不同组件之间的数据是无法相互使用.组件间如何传递数据就显得至关重要,这篇文章主要是介绍Vuex.尽量以通俗易懂的实例讲述这其中的差别 ...

  8. WeChatSampleBuilder V2.0 使用教程(网页版+桌面版)

    为了方便开发者可以快速搭建一个最小化所需模块的 Senparc.Weixin SDK Sample 项目,我们于 2018 年 11 月发布了首个 WeChatSampleBuilder 的版本,受到 ...

  9. css实现水平垂直居中的几种方式

    梳理下平时常用css水平垂直居中方式- 使用flex布局 HTML <div class="box"> <div class="child"& ...

  10. Https双向验证与Springboot整合测试-人来人往我只认你

    1 简介 不知不觉Https相关的文章已经写了6篇了,本文将是这个专题的最后一篇,起码近期是最后一篇.前面6篇讲的全都是单向的Https验证,本文将重点介绍一下双向验证.有兴趣的同学可以了解一下之前的 ...