1. 程式人生 > >MySQL查詢優化之行構造器表示式

MySQL查詢優化之行構造器表示式

原文地址:https://dev.mysql.com/doc/refman/5.7/en/row-constructor-optimization.html

譯文:

8.2.1.19 行構造器表示式優化

行構造函器允許同時比較多個值。例如,下面兩個語句在語義上是等價的:

  • SELECT * FROM t1 WHERE (column1,column2) = (1,1);
    SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;

此外,優化器以相同的方式處理這兩個表示式。

如果行構造函器列不包含索引的字首,優化器就不太可能使用可用的索引。考慮下表,它在(c1, c2, c3)上有一個主鍵:

  • CREATE TABLE t1 (
      c1 INT, c2 INT, c3 INT, c4 CHAR(100),
      PRIMARY KEY(c1,c2,c3)
    );

在這個查詢中,WHERE子句使用索引中的所有列。但是,行構造器本身不包含索引字首,結果優化器只使用c1 (key_len=4, c1的大小):

  • mysql> EXPLAIN SELECT * FROM t1
           WHERE c1=1 AND (c2,c3) > (1,1)\G
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: t1
       partitions: NULL
             type: ref
    possible_keys: PRIMARY
              key: PRIMARY
          key_len: 4
              ref: const
             rows: 3
         filtered: 100.00
            Extra: Using where

在這種情況下,使用等效的非構造器表示式重寫行構造器表示式可能會導致更完整的索引使用。對於上述給定的查詢,行構造器和等價的非構造器表示式為:

  • (c2,c3) > (1,1)
    c2 > 1 OR ((c2 = 1) AND (c3 > 1))

重寫查詢以使用非構造器表示式會導致優化器使用索引中的所有三列(key_len=12):

  • mysql> EXPLAIN SELECT * FROM t1
           WHERE c1 = 1 AND (c2 > 1 OR ((c2 = 1) AND (c3 > 1)))\G
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: t1
       partitions: NULL
             type: range
    possible_keys: PRIMARY
              key: PRIMARY
          key_len: 12
              ref: NULL
             rows: 3
         filtered: 100.00
            Extra: Using where

因此,為了獲得更好的結果,避免將行構造器與AND/OR表示式混合。使用其中之一。

在某些條件下,優化器可以對具有行構造器引數的IN()表示式應用範圍訪問方法。具體可參考Range Optimization of Row Constructor Expressions

PS:由於水平有限,譯文中難免會存在謬誤,歡迎批評指正。