#### 8.2.1.22 行构造函数表达式优化

[](<>)[](<>)

行构造函数允许同时比较多个值。例如，这两个语句在语义上是等价的：

```
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)
);
```

在这个查询中，`在哪里`子句使用索引中的所有列。但是，行构造函数本身不包含索引前缀，因此优化器仅使用`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
```

因此，为了获得更好的结果，请避免将行构造函数与[`和`](logical-operators.html#operator_and)/[`要么`](logical-operators.html#operator_or)表达式。使用其中一种。

在某些条件下，优化器可以将范围访问方法应用于[`在（）`](comparison-operators.html#operator_in)具有行构造函数参数的表达式。看[行构造函数表达式的范围优化](range-optimization.html#row-constructor-range-optimization).
