iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >子查询合并Derived_merge
  • 829
分享到

子查询合并Derived_merge

2024-04-02 19:04:59 829人浏览 泡泡鱼
摘要

1、Derived_merge简介Mysql Reference manual是这么描述的:The derived_merge flag controls whether the optimizer att

1、Derived_merge简介

Mysql Reference manual是这么描述的:

The derived_merge flag controls whether the optimizer attempts to merge subqueries and views in the FROM clause into the outer query block, assuming that no other rule prevents merging. By default, the flag is on to enable merging. Setting the flag to off prevents merging.


其实derived_merge是系统变量optimizer_switch众多参数中的一个参数选项,从5.7.6版本(包括5.7.6)开始支持,默认值是derived_merge=on,用来控制优化器是否合并衍生表或视图的。


注意

本文实验的所有环境都是mysql8.0.13;

derived_merge是Mysql5,6和MySQL5.7比较重要的一个区别,对SQL优化很是重要,笔者曾遇到过相关案例,类似于本文第4部分案例。


2.Derived_merge示例

select * from (select * from t_group)as t1;

子查询合并后等价于select * from  t_group;

设置derived_merge=on,从执行计划和warnings中可以看到from后面的子查询被合并了,

mysql> set optimizer_switch='derived_merge=on';

mysql> desc select * from (select * from t_group)as t1;
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | t_group | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL  |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message:  select `employees`.`t_group`.`emp_no` AS `emp_no`,`employees`.`t_group`.`dept_no` AS `dept_no`,`employees`.`t_group`.`from_date` AS `from_date`,`employees`.`t_group`.`to_date` AS `to_date` from `employees`.`t_group`
1 row in set (0.00 sec)


设置derived_merge=off,从执行计划和warnings中可以看到from后面的子查询仍然是独立的一个子查询,并没有去掉括号被合并

mysql> set optimizer_switch='derived_merge=off';

mysql> desc select * from (select * from t_group)as t1;
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | PRIMARY     | <derived2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL  |
|  2 | DERIVED     | t_group    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL  |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
2 rows in set, 1 warning (0.00 sec)

mysql> desc select * from (select * from t_group)as t1;
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | PRIMARY     | <derived2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL  |
|  2 | DERIVED     | t_group    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL  |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
2 rows in set, 1 warning (0.00 sec)

mysql> show warnings\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message:  select `t1`.`emp_no` AS `emp_no`,`t1`.`dept_no` AS `dept_no`,`t1`.`from_date` AS `from_date`,`t1`.`to_date` AS `to_date` from ( select `employees`.`t_group`.`emp_no` AS `emp_no`,`employees`.`t_group`.`dept_no` AS `dept_no`,`employees`.`t_group`.`from_date` AS `from_date`,`employees`.`t_group`.`to_date` AS `to_date` from `employees`.`t_group`) `t1`
1 row in set (0.00 sec)


3、防止Derived_merge的一些技巧

因为derived_merge默认是on,但是有时候我们又不想通过修改配置参数不让子查询合并,那么还有其他办法吗?当然,可以通过在子查询中添加关键字的方法:

聚合函数 (SUM(), MIN(), MAX(), COUNT(), and so forth)

distinct

group by

having

limit

uNIOn or union all

使用变量符号@


例如:

mysql> desc select * from (select count(*) from t_group)as t1;
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table      | partitions | type   | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+-------+
|  1 | PRIMARY     | <derived2> | NULL       | system | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
|  2 | DERIVED     | t_group    | NULL       | ALL    | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL  |
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+-------+
2 rows in set, 1 warning (0.00 sec)

mysql> desc select * from (select distinct * from t_group)as t1;
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | PRIMARY     | <derived2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL            |
|  2 | DERIVED     | t_group    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | Using temporary |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
2 rows in set, 1 warning (0.00 sec)

mysql> desc select * from (select dept_no from t_group group by dept_no)as t1;
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | PRIMARY     | <derived2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL            |
|  2 | DERIVED     | t_group    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | Using temporary |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
2 rows in set, 1 warning (0.00 sec)

mysql> desc select * from (select * from t_group having emp_no > 15000)as t1;
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | PRIMARY     | <derived2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL  |
|  2 | DERIVED     | t_group    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL  |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
2 rows in set, 1 warning (0.00 sec)

mysql> desc select * from (select * from t_group union select * from t_order)as t1;
+----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type  | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | PRIMARY      | <derived2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   20 |   100.00 | NULL            |
|  2 | DERIVED      | t_group    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL            |
|  3 | UNION        | t_order    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL            |
| NULL | UNION RESULT | <union2,3> | NULL       | ALL  | NULL          | NULL | NULL    | NULL | NULL |     NULL | Using temporary |
+----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
4 rows in set, 1 warning (0.00 sec)

mysql> desc select * from t_group t join (select @rn:=10001 emp_no)e on t.emp_no=e.emp_no;
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+----------------+
| id | select_type | table      | partitions | type   | possible_keys | key  | key_len | ref  | rows | filtered | Extra          |
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+----------------+
|  1 | PRIMARY     | <derived2> | NULL       | system | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL           |
|  1 | PRIMARY     | t          | NULL       | ALL    | NULL          | NULL | NULL    | NULL |   10 |    10.00 | Using where    |
|  2 | DERIVED     | NULL       | NULL       | NULL   | NULL          | NULL | NULL    | NULL | NULL |     NULL | No tables used |
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+----------------+
3 rows in set, 2 warnings (0.00 sec)


4、如果子查询数据量特别大,子查询合并可以起到优化SQL的效果,相当于减少了子查询执行次数。

例如如下一条SQL,当关闭子查询合并功能的时候,SQL执行需要9秒多,开启子查合并功能后,时间为5秒,效率提高了1倍;

如果当前使用的是MySQL5,6版本,不支持derived_merge功能,这个时候我们可以通过改写SQL,减少子查询的方法来提高SQL效率,这也是优化SQL的一条思路。


没有发生子查询合并的SQL执行情况:

set optimizer_switch='derived_merge=off';

mysql> select
    -> total.emp_no,
    -> total.salary,
    -> total.to_date,
    -> total.last_name,
    -> total.hire_date
    -> from
    -> (select
    -> s.emp_no emp_no,
    -> s.salary salary,
    -> s.to_date to_date,
    -> e.last_name last_name,
    -> e.hire_date hire_date
    -> from salaries s
    -> inner join employees e where s.emp_no=e.emp_no) total;
2844047 rows in set (9.48 sec)

mysql> desc select
    -> total.emp_no,
    -> total.salary,
    -> total.to_date,
    -> total.last_name,
    -> total.hire_date
    -> from
    -> (select
    -> s.emp_no emp_no,
    -> s.salary salary,
    -> s.to_date to_date,
    -> e.last_name last_name,
    -> e.hire_date hire_date
    -> from salaries s
    -> inner join employees e where s.emp_no=e.emp_no limit 10000000) total;
+----+-------------+------------+------------+------+----------------+---------+---------+-----------------+---------+----------+-------+
| id | select_type | table      | partitions | type | possible_keys  | key     | key_len | ref             | rows    | filtered | Extra |
+----+-------------+------------+------------+------+----------------+---------+---------+-----------------+---------+----------+-------+
|  1 | PRIMARY     | <derived2> | NULL       | ALL  | NULL           | NULL    | NULL    | NULL            | 2995588 |   100.00 | NULL  |
|  2 | DERIVED     | e          | NULL       | ALL  | PRIMARY        | NULL    | NULL    | NULL            |  299512 |   100.00 | NULL  |
|  2 | DERIVED     | s          | NULL       | ref  | PRIMARY,emp_no | PRIMARY | 4       | testdb.e.emp_no |      10 |   100.00 | NULL  |
+----+-------------+------------+------------+------+----------------+---------+---------+-----------------+---------+----------+-------+
3 rows in set, 1 warning (0.00 sec)

mysql> show warnings\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message:  select `total`.`emp_no` AS `emp_no`,`total`.`salary` AS `salary`,`total`.`to_date` AS `to_date`,`total`.`last_name` AS `last_name`,`total`.`hire_date` AS `hire_date` from ( select `testdb`.`s`.`emp_no` AS `emp_no`,`testdb`.`s`.`salary` AS `salary`,`testdb`.`s`.`to_date` AS `to_date`,`testdb`.`e`.`last_name` AS `last_name`,`testdb`.`e`.`hire_date` AS `hire_date` from `testdb`.`salaries` `s` join `testdb`.`employees` `e` where (`testdb`.`s`.`emp_no` = `testdb`.`e`.`emp_no`) limit 10000000) `total`
1 row in set (0.00 sec)


发生子查询合并的SQL执行情况:

mysql> set optimizer_switch='derived_merge=on';

mysql> select
    -> total.emp_no,
    -> total.salary,
    -> total.to_date,
    -> total.last_name,
    -> total.hire_date
    -> from
    -> (select
    -> s.emp_no emp_no,
    -> s.salary salary,
    -> s.to_date to_date,
    -> e.last_name last_name,
    -> e.hire_date hire_date
    -> from salaries s
    -> inner join employees e where s.emp_no=e.emp_no) total;
2844047 rows in set (5.03 sec)

mysql> desc select
    -> total.emp_no,
    -> total.salary,
    -> total.to_date,
    -> total.last_name,
    -> total.hire_date
    -> from
    -> (select
    -> s.emp_no emp_no,
    -> s.salary salary,
    -> s.to_date to_date,
    -> e.last_name last_name,
    -> e.hire_date hire_date
    -> from salaries s
    -> inner join employees e where s.emp_no=e.emp_no) total;
+----+-------------+-------+------------+------+----------------+---------+---------+-----------------+--------+----------+-------+
| id | select_type | table | partitions | type | possible_keys  | key     | key_len | ref             | rows   | filtered | Extra |
+----+-------------+-------+------------+------+----------------+---------+---------+-----------------+--------+----------+-------+
|  1 | SIMPLE      | e     | NULL       | ALL  | PRIMARY        | NULL    | NULL    | NULL            | 299512 |   100.00 | NULL  |
|  1 | SIMPLE      | s     | NULL       | ref  | PRIMARY,emp_no | PRIMARY | 4       | testdb.e.emp_no |     10 |   100.00 | NULL  |
+----+-------------+-------+------------+------+----------------+---------+---------+-----------------+--------+----------+-------+
2 rows in set, 1 warning (0.00 sec)

mysql> show warnings\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message:  select `testdb`.`s`.`emp_no` AS `emp_no`,`testdb`.`s`.`salary` AS `salary`,`testdb`.`s`.`to_date` AS `to_date`,`testdb`.`e`.`last_name` AS `last_name`,`testdb`.`e`.`hire_date` AS `hire_date` from `testdb`.`salaries` `s` join `testdb`.`employees` `e` where (`testdb`.`s`.`emp_no` = `testdb`.`e`.`emp_no`)
1 row in set (0.00 sec)


参考链接

Section 8.2.2.3, “Optimizing Derived Tables and View References”.

您可能感兴趣的文档:

--结束END--

本文标题: 子查询合并Derived_merge

本文链接: https://www.lsjlt.com/news/40969.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 【MySQL系列】MySQL复合查询的学习 _ 多表查询 | 自连接 | 子查询 | 合并查询
    「前言」文章内容大致是对MySQL复合查询的学习。 「归属专栏」MySQL 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、基本查询回顾二、多表查询三、自连接四、子查询4.1 单行子查询4.2 多行子查询4....
    99+
    2023-08-30
    mysql 学习 android
  • 详解MySQL子查询(嵌套查询)、联结表、组合查询
    一、子查询 MySQL 4.1版本及以上支持子查询 子查询:嵌套在其他查询中的查询。 子查询的作用: 1、进行过滤: 实例1:检索订购物品TNT2的所有客户的ID = + 一般,在WHERE...
    99+
    2024-04-02
  • Mysql---子查询的三种查询方式( 表子查询,条件子查询,列中子查询)
    mysql子查询 子查询分为: 列中子查询 单列单行表子查询 必须有别名条件子查询 单行单列 多行单列 下列示例表结构: grade表: result表: student表: subject表:...
    99+
    2023-09-04
    mysql sql 数据库
  • MySQL子查询详解(单行子查询、多行子查询与相关子查询)
    目录0.概念1.需求分析与问题解决1.1提出具体问题:1.2 子查询的基本使用: 子查询的基本语法结构:1.3 子查询的分类2.单行子查询2.1实例:2.2空值问题2.3非法使用子查...
    99+
    2024-04-02
  • Mysql中怎么实现子查询和联合查询
    Mysql中怎么实现子查询和联合查询,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。查询: 在select查...
    99+
    2024-04-02
  • mysql如何查询后合并
    这篇“mysql如何查询后合并”文章,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要参考一下,对于“mysql如何查询后合并”,小编整理了以下知识点,请...
    99+
    2024-04-02
  • MySQL如何合并查询结果
    今天小编给大家分享一下MySQL如何合并查询结果的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下...
    99+
    2023-04-06
    mysql
  • MySQL查询数据之合并查询结果的案例
    小编给大家分享一下MySQL查询数据之合并查询结果的案例,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!.利用union...
    99+
    2024-04-02
  • C/C++并查集的查询与合并实现原理
    目录一、并查集的概念二、并查集的实现1.并查集不同集合(树)的形成2.find()函数找一个元素集合的编号3.合并两个不同集合(合并两棵不同的树)4.查询两个元素是否在一个集合5.并...
    99+
    2023-02-13
    C++并查集的查询与合并 C语言并查集的合并与查询
  • MySQL子查询(嵌套查询)
    子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从 MySQL 4.1 开始引入。 在SELECT 子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一 个表或者多个表。子查询中常用的操作符有 AN...
    99+
    2023-09-04
    mysql 数据库 sql Powered by 金山文档
  • MYSQL——子查询
       MYSQL的子查询1   求平均值   SELECT AVG (字段 如good_price) FROM  tdb_表名;...
    99+
    2024-04-02
  • MySQL进阶查询、聚合查询和联合查询
    目录1. 前言2. 表的设计2.1 一对一2.2 一对多2.3 多对多3.将查询结果放到另一个表中4. 聚合查询4.2 GROUP BY4.3 HAVING5. 联合查询(多表查询)5.1 内连接5.2 外连接5...
    99+
    2023-04-12
    MySQL进阶查询 MySQL聚合查询 MySQL联合查询
  • 【MySQL】进阶查询-聚合查询和联合查询
    文章目录 1. 前言2. 表的设计2.1 一对一2.2 一对多2.3 多对多 3.将查询结果放到另一个表中4. 聚合查询4.1 聚合函数4.2 GROUP BY4.3 HAVING 5. 联合查询(多表查询)5.1 ...
    99+
    2023-08-17
    mysql 数据库 sql
  • SQLSERVER实现连接与合并查询
    创建测试表MyStudentInfo CREATE table MyStudentInfo ( Id int not null primary key, Name varcha...
    99+
    2024-04-02
  • mysql查询结果该如何合并
    这篇文章给大家介绍mysql查询结果该如何合并,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。在mysql中,可以利用UNION操作符来合并查询结果,该操作符用于将两个以上的SE...
    99+
    2024-04-02
  • MySQL --- 聚合查询 和 联合查询
    聚合查询: 下文中的所有聚合查询的示例操作都是基于此表: 聚合函数 聚合函数都是行与行之间的运算。 count() select count(列名) from 表名; 统计该表中该列的行数,但是 null 值不会统计在内,但是...
    99+
    2023-10-21
    mysql 数据库 sql
  • mysql怎么查询合并两条数据
    要查询合并两条数据,可以使用UNION操作符进行合并。例如: SELECT column1, column2 FRO...
    99+
    2024-04-09
    mysql
  • sql两个查询结果怎么合并
    要合并两个查询结果,可以使用UNION操作符。UNION操作符将两个查询结果合并为一个结果集,并去除重复的行。 例如...
    99+
    2024-04-09
    sql
  • Oracle中怎么将查询结果合并
    在Oracle中,可以使用UNION或UNION ALL关键字将查询结果合并到一个结果集中。 UNION关键...
    99+
    2024-04-09
    Oracle
  • mysql标量子查询和非法子查询的区别
    这篇文章主要讲解了“mysql标量子查询和非法子查询的区别”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mysql标量子查询和非法子查询的区别”吧!#whe...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作