MYSQL ( field1, field2 ) = (x,y) 与 field1= x AND field2 = Y 之间的差异
MYSQL Difference between ( field1, field2 ) = (x,y) vs field1= x AND field2 = Y
我有一个 table studentDB,其中包含以下字段
select sid, sname, sDOB from Student
我看过很多地方,(xx,yy)和AND有什么区别,哪个更性能更好
select * from Student where (sid,sname) = (101,'foo')
对
select * from Student where sid = 101 AND sname = 'foo'
以及用于匹配时此运算符 () 的名称是什么?
(sid,sname)
被称为“元组”,一些数据库引擎在不同程度上支持它们。 MySQL8 做得很好
现在,这两个表达式在使用相等时没有区别。但是,元组对于不等式可能非常有用。例如:
select * from t where (a, b) <= (1, 0)
不同于:
select * from t where a <= 1 and b <= 0
当使用元组时,元素的比较是按顺序进行的,一个接一个。请参阅 DB Fiddle.
中的差异示例
行构造函数比较在SQL语法中是合法的,但在MySQL5.5及更早版本中,此语法不支持索引优化,因此不鼓励使用。
见https://dev.mysql.com/doc/refman/8.0/en/row-constructor-optimization.html
到目前为止,所有支持的 MySQL 版本都支持行构造函数比较的索引优化。缺少此功能的旧版本已过期,因此您无论如何都不应该使用这些旧版本。因此,没有理由再避免这种语法了。
2013-12-03 MySQL 5.7.3 更新日志:
The optimizer now is able to apply the range scan access method to
queries of this form:
SELECT ... FROM t1 WHERE ( col_1, col_2 ) IN (( 'a', 'b' ), ( 'c', 'd' ));
Previously, for range scans to be used it was necessary for the
query to be written as:
SELECT ... FROM t1 WHERE ( col_1 = 'a' AND col_2 = 'b' ) OR ( col_1 = 'c' AND col_2 = 'd' );
For the optimizer to use a range scan, queries
must satisfy these conditions:
Only IN
predicates can be used, not NOT IN
.
There may only be column references in the row constructor on the IN
predicate's left hand side.
There must be more than one row constructor on the IN predicate's
right hand side.
Row constructors on the IN predicate's right hand side must contain
only runtime constants, which are either literals or local column
references that are bound to constants during execution.
EXPLAIN output for applicable queries will change from full table or
index scan to range scan. Changes are also visible by checking the
values of the
Handler_read_first,
Handler_read_key,
and
Handler_read_next
status variables.
(我不知道 MariaDB 是否进行了优化。)
我有一个 table studentDB,其中包含以下字段
select sid, sname, sDOB from Student
我看过很多地方,(xx,yy)和AND有什么区别,哪个更性能更好
select * from Student where (sid,sname) = (101,'foo')
对
select * from Student where sid = 101 AND sname = 'foo'
以及用于匹配时此运算符 () 的名称是什么?
(sid,sname)
被称为“元组”,一些数据库引擎在不同程度上支持它们。 MySQL8 做得很好
现在,这两个表达式在使用相等时没有区别。但是,元组对于不等式可能非常有用。例如:
select * from t where (a, b) <= (1, 0)
不同于:
select * from t where a <= 1 and b <= 0
当使用元组时,元素的比较是按顺序进行的,一个接一个。请参阅 DB Fiddle.
中的差异示例行构造函数比较在SQL语法中是合法的,但在MySQL5.5及更早版本中,此语法不支持索引优化,因此不鼓励使用。
见https://dev.mysql.com/doc/refman/8.0/en/row-constructor-optimization.html
到目前为止,所有支持的 MySQL 版本都支持行构造函数比较的索引优化。缺少此功能的旧版本已过期,因此您无论如何都不应该使用这些旧版本。因此,没有理由再避免这种语法了。
2013-12-03 MySQL 5.7.3 更新日志:
The optimizer now is able to apply the range scan access method to queries of this form:
SELECT ... FROM t1 WHERE ( col_1, col_2 ) IN (( 'a', 'b' ), ( 'c', 'd' ));
Previously, for range scans to be used it was necessary for the query to be written as:
SELECT ... FROM t1 WHERE ( col_1 = 'a' AND col_2 = 'b' ) OR ( col_1 = 'c' AND col_2 = 'd' );
For the optimizer to use a range scan, queries must satisfy these conditions:Only
IN
predicates can be used, notNOT IN
.There may only be column references in the row constructor on the IN predicate's left hand side.
There must be more than one row constructor on the IN predicate's right hand side.
Row constructors on the IN predicate's right hand side must contain only runtime constants, which are either literals or local column references that are bound to constants during execution.
EXPLAIN output for applicable queries will change from full table or index scan to range scan. Changes are also visible by checking the values of the Handler_read_first, Handler_read_key, and Handler_read_next status variables.
(我不知道 MariaDB 是否进行了优化。)