Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Row Constructor Expression Optimization

10.2.1.22 Row Constructor Expression 优化

行构造器允许同时比较多个值。例如,这两个语句是语义等价的:

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=4c1的大小):

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()表达式的范围访问方法应用于具有行构造器参数的表达式。请参阅行构造器范围优化