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”.

      

  • 相关阅读:
    OnEraseBkgnd、OnPaint与画面重绘
    .编译ADO类DLL时报错的解决方案
    VC列表框样式
    Codeforces 131D. Subway 寻找环树的最短路径
    Codeforces 103B. Cthulhu 寻找奈亚子
    Codeforces 246D. Colorful Graph
    Codeforces 278C. Learning Languages 图的遍历
    Codeforces 217A. Ice Skating 搜索
    Codeforces 107A. Dorm Water Supply 搜图
    Codeforces 263 D. Cycle in Graph 环
  • 原文地址:https://www.cnblogs.com/bigbigbigo/p/10965310.html
Copyright © 2011-2022 走看看