MySQL 子查詢(四)子查詢的優化、將子查詢重寫爲鏈接

  MySQL 5.7 ref ——13.2.10.10優化子查詢html

10、子查詢的優化mysql

  開發正在進行中,所以從長遠來看,沒有什麼優化建議是可靠的。如下列表提供了一些您可能想要使用的有趣技巧。See also Section 8.2.2, 「Optimizing Subqueries, Derived Tables, and View References」.sql

  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.

 

11、將子查詢重寫爲鏈接

  有時,除了使用子查詢以外,還有其餘方法能夠測試一組值中的成員資格。

  一樣,在某些狀況下,不只能夠將查詢重寫爲沒有子查詢的語句,還可能比使用子查詢更加高效。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」.

相關文章
相關標籤/搜索