介绍
行构造函数允许同时比较多个值。举例来说,这两个语句在语义上是等价的:
SELECT * FROM t1 WHERE (column1,column2) = (1,1);
SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
同时,优化器采用相同的方式处理两个SQL语句。
如果行构造函数列未覆盖索引的前缀,则优化程序不太可能使用可用索引。思考下面这张表,这张表有主键在(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, the size of 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))
重写查询以使用非构造函数表达式会导致优化程序使用索引中的所有三列:
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表达式混合。 使用其中一个。