zoukankan      html  css  js  c++  java
  • MySQL 子查询(四)子查询的优化、将子查询重写为连接

      MySQL 5.7 ref ——13.2.10.10优化子查询

    十、子查询的优化

      开发正在进行中,因此从长远来看,没有什么优化建议是可靠的。以下列表提供了一些您可能想要使用的有趣技巧。See also Section 8.2.2, “Optimizing Subqueries, Derived Tables, and View References”.

      10.1 优化子查询中行的数量或顺序

    SELECT * FROM t1 WHERE t1.column1 IN
      (SELECT column1 FROM t2 ORDER BY column1);
    
    SELECT * FROM t1 WHERE t1.column1 IN
      (SELECT DISTINCT column1 FROM t2);
    
    SELECT * FROM t1 WHERE EXISTS
      (SELECT * FROM t2 LIMIT 1);

      10.2 用子查询替换连接

    SELECT DISTINCT column1 
    FROM t1 WHERE t1.column1 IN (
        SELECT column1 FROM t2
    );

      用上面的语句替换这下面的:

    SELECT DISTINCT t1.column1 
    FROM t1, t2
    WHERE t1.column1 = t2.column1;

      10.3

      某些子查询可以转换为连接,以便与不支持子查询的旧版MySQL兼容。但是,在某些情况下,将子查询转换为连接可能会提高性能。

      10.4 子句从外部移动到子查询内部

      例如,用上面的查询代替下面的:

    SELECT * FROM t1
    WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);
    
    /*代替*/
    
    SELECT * FROM t1
    WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);

      另一个例子:

    SELECT (SELECT column1 + 5 FROM t1) FROM t2;
    
    /*代替*/
    
    SELECT (SELECT column1 FROM t1) + 5 FROM t2;

      10.5 使用行子查询而不是相关子查询。

    SELECT * FROM t1
      WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);
    
    /*代替*/
    
    SELECT * FROM t1
      WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1
                    AND t2.column2=t1.column2);

      

      10.6

      使用 

    NOT (a = ANY (...))

      而不是

    a <> ALL (...)

      10.7

      使用 

    x = ANY (table containing (1,2))

      而不是

    x=1 OR x=2.

      10.8

      使用

    =ANY

      而不是

    EXISTS

      10.9

      对于始终返回一行的不相关子查询,IN 总是慢于 =

    SELECT * FROM t1
      WHERE t1.col_name = (SELECT a FROM t2 WHERE b = some_const);
    
    /*代替*/
    
    SELECT * FROM t1
      WHERE t1.col_name IN (SELECT a FROM t2 WHERE b = some_const);

      这些技巧可能会导致程序变得更快或更慢。使用像BENCHMARK() 函数这样的MySQL工具,您可以了解在您自己的情况下有什么帮助。See Section 12.15, “Information Functions”.

      MySQL自己也会做出一些优化:

    • MySQL只执行一次不相关的子查询。使用EXPLAIN确保给定的子查询确实不相关。
    • MySQL会重写IN,ALL,ANY和SOME子查询,这样是为了尝试提高子查询中的select-list列被索引的可能性。
    • MySQL使用索引查找函数替换以下形式的子查询,EXPLAIN将其描述为特殊的连接类型(unique_subquery或index_subquery:
      ... IN (SELECT indexed_column FROM single_table ...)
    • MySQL使用包含MIN()或MAX()的表达式增强以下表单的表达式,除非涉及NULL值或空集:
      value {ALL|ANY|SOME} {> | < | >= | <=} (uncorrelated subquery)

      例如,对这个WHERE子句

      WHERE 5 > ALL (SELECT x FROM t)

      优化器可能会像这样对待:

      WHERE 5 > (SELECT MAX(x) FROM t)

      

      See also MySQL Internals: How MySQL Transforms Subqueries.

    十一、将子查询重写为连接

      有时,除了使用子查询之外,还有其他方法可以测试一组值中的成员资格。

      同样,在某些情况下,不仅可以将查询重写为没有子查询的语句,还可能比使用子查询更加高效。IN()构造器就是如此。

      例如,这个查询:

    SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);

      可以被重写为:

    SELECT DISTINCT t1.* FROM t1, t2 WHERE t1.id=t2.id;

      查询:

    SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);
    SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);

      可以被重写为:

    SELECT table1.*
      FROM table1 LEFT JOIN table2 ON table1.id=table2.id
      WHERE table2.id IS NULL;

      LEFT [OUTER] JOIN可以比等效子查询更快,因为服务器可能能够更好地优化它——这个事实并非仅针对MySQL Server。

      在SQL-92之前,外连接不存在,因此子查询是执行某些操作的唯一方法。今天,MySQL Server和许多其他现代数据库系统提供了广泛的外连接类型。

      MySQL Server支持多表DELETE语句,可用于根据一个表甚至多个表中的信息同时有效地删除行。还支持多表UPDATE语句。See Section 13.2.2, “DELETE Syntax”, and Section 13.2.11, “UPDATE Syntax”.

      

  • 相关阅读:
    Failed to load resource: net::ERR_FILE_NOT_FOUND
    gulp安装详解
    npm install gulp-cli -g时npm ERR! code ECONNREFUSED
    webpack4.43
    修改cmd默认路径
    delphi设置鼠标图形
    Linux常用命令学习
    IO模型介绍 以及同步异步阻塞非阻塞的区别
    TCP的三次握手与四次挥手过程,各个状态名称与含义
    常见的设计模式详解:单例模式、工厂模式、观察者模式
  • 原文地址:https://www.cnblogs.com/bigbigbigo/p/10965310.html
Copyright © 2011-2022 走看看