MYSQL优化派生表(子查询)在From语句中的
Mysql 在5.6.3中,优化器更有效率地处理派生表(在from语句中的子查询):
优化器推迟物化子查询在from语句中的子查询,知道子查询的内容在查询正真执行需要时,才开始物化。这一举措提高了性能:
1:之前版本(5.6.3),from语句中的子查询在explain select 查看执行计划语句执行时就会物化。它导致了部分查询执行,但explain语句的目的是获取执行计划信息,而不是执行查询
该版本物化不会在explain中发生,所以explain执行计划结果的得到更快;
2:因为上面提及的,物化子查询的推迟有可能不会发生。考虑一个from语句中的子查询的结果和另一个表join(链接)查询,如果优化器先处理另一张表A,然后发现A中没有满足条件的行返回,此时join不会再继续执行,并且优化器会完全跳过物化子查询这步骤;
考虑下面的explain语句,子查询出现在form语句中;
EXPLAIN SELECT * FROM (SELECT * FROM t1) AS derived_t1;
优化器避免物化子查询直到子查询的结果在查询真正执行需要时。在上面情况下,查询并没有执行,所有并没有物化(子查询);
即使查询执行时,也会要求优化器去避免物化。考虑下面的查询:
SELECT *
FROM t1 JOIN (SELECT t2.f1 FROM t2) AS derived_t2 ON t1.f2=derived_t2.f1
WHERE t1.f1 > 0;
如果优化器先处理t1,并且where语句产生个空集,join结果必定是空集并且该子查询没必要去物化。
最坏的情况(派生表被物化),查询执行会花费和之前版本之前的时间,在最好的情况下(派生表不会物化),查询执行更快。
在派生表需要物化的情况下,优化器会通过为物化表添加索引来加速访问物化表的结果,如果添加的索引允许ref方式访问该物化表,会更好的减少在查询执行时读取的数据量。考虑下面的查询:
SELECT *
FROM t1 JOIN (SELECT DISTINCT f1 FROM t2) AS derived_t2
ON t1.f1=derived_t2.f1;
优化器在derived_t2派生表f1列构造一个索引,如果这样允许ref方式来最小化执行计划的话费,添加索引,优化器对待物化的派生表和平常的带index表一样,添加index的花费比起查询没有Index的执行无不足道,如果ref方式比其他访问方式花费更多,index不会添加,优化器不会做任何优化。
<======================分割线==================================>
From子查询形式:
SELECT ... FROM (subquery) [AS] name ...
[AS] Name 语句是强制的(必须加上的), 因为From语句中每个表必须有一个名字. 子查询中的每个select列必须有一个唯一的名字。
CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);
INSERT INTO t1 VALUES (1,'',1.0);
INSERT INTO t1 VALUES (2,'',2.0);
SELECT sb1,sb2,sb3
FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb
WHERE sb1 > 1;
Result: 2, '2', 4.0.
另一个例子:目的是想得到一组集合和的平均值。 下面的语句并不起作用:
SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;
正确格式:
SELECT AVG(sum_column1)
FROM (SELECT SUM(column1) AS sum_column1
FROM t1 GROUP BY column1) AS t1;
From语句中的子查询会返回一个标量一列,一行或者一个表。from语句中的子查询不能是相关子查询,除非有on 或者join关键字.
在Mysql5.6.3之前,from语句中的子查询会在explain语句中执行(派生临时表会被物化)。因为上层查询需要得到所有表的信息在优化阶段。在某些情况下用explain select语句会修改表数据,如果外部查询访问所有表,并且内部查询调用一个修改表数据行的存储方法,见下:
mysql> create table t1(c1 int);
Query OK, 0 rows affected (0.39 sec) mysql> create table t2(c1 int);
Query OK, 0 rows affected (0.26 sec)
现在创建一个修改t2表的存储方法;
mysql> delimiter //
mysql> create function f1(p1 int) returns int
-> begin
-> insert into t2 values(p1);
-> return p1;
-> end //
Query OK, 0 rows affected (0.00 sec) mysql> delimiter ;
直接引用该存储方法在一个explain select 语句中不会对t2有任何作用;
mysql> select * from t2;
Empty set (0.00 sec) mysql> explain select f1(5);
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
这是因为select语句没用引用任何表, 可以在table和extra列中输出看到:
mysql> explain select now() as a1,(select f1(5)) as a2;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set, 1 warning (0.00 sec) mysql> show warnings;
+-------+------+------------------------------------------+
| Level | Code | Message |
+-------+------+------------------------------------------+
| Note | 1249 | Select 2 was reduced during optimization |
+-------+------+------------------------------------------+
1 row in set (0.00 sec)
然而, 当外部select引用任何表时,优化器会执行子查询:
mysql> explain select * from t1 as a1,(select f1(5)) as a2;
+----+-------------+------------+--------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+------+---------+------+------+----------------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | NULL |
| 1 | PRIMARY | a1 | ALL | NULL | NULL | NULL | NULL | 1 | NULL |
| 2 | DERIVED | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+----+-------------+------------+--------+---------------+------+---------+------+------+----------------+
3 rows in set (0.02 sec) mysql> select * from t2;
+------+
| c1 |
+------+
| 5 |
+------+
1 row in set (0.00 sec)
这也意味着一个explain select语句(如上)也会需要一段时间来执行.
MYSQL优化派生表(子查询)在From语句中的的更多相关文章
- mysql优化---in型子查询,exists子查询,from 型子查询
in型子查询引出的陷阱:(扫更少的行,不要临时表,不要文件排序就快) 题: 在ecshop商城表中,查询6号栏目的商品, (注,6号是一个大栏目) 最直观的: mysql); 误区: 给我们的感觉是, ...
- 子查询在UPDATE 语句中的应用
在UPDATE语句中可以在更新列表中以及WHERE语句使用子查询.下面演示一个将图书的出版日期全部更新为所有图书中的最新出版日期,SQL语句如下: UPDATE T_Book SET FYearPub ...
- 子查询在DELETE语句中的应用
子查询在DELETE 中唯一可以应用的位置就是WHERE 子句,使用子查询可以完成复杂的数据删除控制.其使用方式与SELECT 语句中的子查询基本相同,而且也可以使用相关子查询等高级的特性.下面的SQ ...
- 子查询在INSERT语句中的应用
在使用INSERT语句的时候,一般都是使用它向数据库中一条条的插入数据,比如: INSERT INTO MyTable(FId,FName,FAge)VALUES(1,"John" ...
- Mysql查询优化器之关于子查询的优化
下面这些sql都含有子查询: mysql> select * from t1 where a in (select a from t2); mysql> select * from (se ...
- MySQL 表子查询
MySQL 表子查询 表子查询是指子查询返回的结果集是 N 行 N 列的一个表数据. MySQL 表子查询实例 下面是用于例子的两张原始数据表: article 表: aid title conten ...
- sql优化-派生表与inner-join
首先来说明一下派生表? 外部的表查询的结果集是从子查询中生成的.如下形式: select ... from (select ....) dt 如上形式中括号中的查询的结果作为外面select语句的查询 ...
- MySQL(八)子查询和分组查询
一.子查询 1.子查询(subquery):嵌套在其他查询中的查询. 例如:select user_id from usertable where mobile_no in (select mobil ...
- sql字段拆分 ,连表子查询获取值
1.连表子查询获取值 select bas.name,bas.id_card_num,bas.mobil_no,gender,bas.birthday,bas.height,bas.weight,pr ...
随机推荐
- mvc4.5更改为mvc4.0方法总结
一:使用MVC4.5创建的项目结果IIS服务器不支持(windows server2008 支持.net4.0),整了半天终于有点眉目了,方法如下: 1.先将项目所在的文件夹找到,去掉文件夹及其文件的 ...
- redux入门指南
前言:大概一个月没有写博客了,这两天正好是周末,就写点东西来梳理下之前几个月的所写与所得; 大概两个月前,学习了一下 redux ,还是一点难度的,花了我一天的时间来搞明白他, 但是都没怎么记录,今天 ...
- 表迁移工具的选型-复制ibd的方法
1.1. 场景 有的时候开放人员自己的库需要帮忙导一些数据,但是表的数据量又很大.虽然说使用mysqldump或mysqlpump也可以导.但是这耗时需要比较久. 记得之前建议开放人员可以直接使用na ...
- 【转载】Linux下的IO监控与分析
近期要在公司内部做个Linux IO方面的培训, 整理下手头的资料给大家分享下 各种IO监视工具在Linux IO 体系结构中的位置 源自 Linux Performance and Tuning G ...
- 【vue系列之三】从一个vue-pdf-shower,说说vue组件和npm包
前言 从去年年初开始,自己便下决心要写一个vue系列的博客,但时至今日,才写系列的第三篇博客,想来甚是惭愧. 但是慢归慢,每一篇都要保证质量,以及要写出自己的心路历程,防止自己工作中填的坑再让读者走一 ...
- 安装cocoapods遇到的问题
1.终端报下面的错误 ERROR: While executing gem ... (Errno::EPERM) Operation not permitted - /usr/bin/pod 解决方 ...
- sort()没有返回值
aList = [1,3,5,2,4] aList = aList.sort() print(aList) None
- 基于FPGA驱动VGA显示图片的小问题
学习VGA显示图片的过程中,遇到了一个小问题,我在显示屏上开了一个60x60的框,放了一张图片进去显示,但是最终的结果如下图所示. 出现了一个竖黑边,看了看代码,分析了一下逻辑没问题,然而看这个显示那 ...
- Grafana最新版本4.3.1安装(后端使用mysql)
环境 CentOS release 6.5 (Final) 64bitzabbix_server (Zabbix) 3.0.3 grafana-4.3.1mysql-5.6.21 一.安装grafan ...
- [译]Dapper教程
脑子里突然浮现出一个想法:尝试翻译一些技术文档.说干就干,先来翻译个最近经常查阅的Dapper教程,有兴趣的园友可以一起参与进来 dapper-tutorial-cn. 什么是Dapper Dappe ...