MYSQL优化派⽣表(⼦查询)在From语句中的
Mysql 在5.6.3中,优化器更有效率地处理派⽣表(在from语句中的⼦查询):
优化器推迟物化⼦查询在from语句中的⼦查询,知道⼦查询的内容在查询正真执⾏需要时,才开始物化。这⼀举措提⾼了性能:
1:之前版本(5.6.3),from语句中的⼦查询在explain select查看执⾏计划语句执⾏时就会物化。它导致了部分查询执⾏,但explain语句的⽬的是获取执⾏计划信息,⽽不是执⾏查询
js正则表达式匹配金额该版本物化不会在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;
sql delete from如果优化器先处理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列必须有⼀个唯⼀的名字。
java经典上机编程题CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);
INSERT INTO t1 VALUES (1,'1',1.0);
INSERT INTO t1 VALUES (2,'2',2.0);
SELECT sb1,sb2,sb3
FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2AS 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 |
springmvc面试教程+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
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 |
+-------+------+------------------------------------------+
mysql语句多表查询| Note |1249|Select2 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 |
+------+
oracle客户端正确安装|5|
+------+
1 row in set (0.00 sec)
这也意味着⼀个explain select语句(如上)也会需要⼀段时间来执⾏.
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论