我有一个包含以下字段的表 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'
并且在用于匹配时这个运算符()的名称是什么?
我有一个包含以下字段的表 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)
被称为“元组”,一些数据库引擎在不同程度上支持它们。MySQL 8 做得很好。
现在,使用相等时,这两个表达式之间没有区别。但是,元组对于不等式可能非常有用。例如:
select * from t where (a, b) <= (1, 0)
不同于:
select * from t where a <= 1 and b <= 0
当使用元组时,元素的比较是按顺序进行的,一个接一个。请参阅DB Fiddle的差异示例。
行构造函数比较在 SQL 语法中是合法的,但在 MySQL 5.5 及更早的版本中,这种语法不支持索引优化,因此不鼓励使用。
见https://dev.mysql.com/doc/refman/8.0/en/row-constructor-optimization.html
到目前为止,所有支持的 MySQL 版本都支持行构造函数比较的索引优化。缺少此功能的旧版本已经过时,因此无论如何您都不应该使用这些旧版本。因此,没有理由再避免这种语法了。
2013-12-03 MySQL 5.7.3 变更日志:
优化器现在能够将范围扫描访问方法应用于这种形式的查询:
SELECT ... FROM t1 WHERE ( col_1, col_2 ) IN (( 'a', 'b' ), ( 'c', 'd' ));
以前,要使用范围扫描,查询必须写为:
SELECT ... FROM t1 WHERE ( col_1 = 'a' AND col_2 = 'b' ) OR ( col_1 = 'c' AND col_2 = 'd' );
为了让优化器使用范围扫描,查询必须满足以下条件:只能
IN
使用谓词,不能使用NOT IN
.IN 谓词左侧的行构造函数中可能只有列引用。
IN 谓词的右侧必须有多个行构造函数。
IN 谓词右侧的行构造函数必须仅包含运行时常量,它们是在执行期间绑定到常量的文字或本地列引用。
适用查询的 EXPLAIN 输出将从全表或索引扫描更改为范围扫描。通过检查Handler_read_first、 Handler_read_key和 Handler_read_next 状态变量的值也可以看到更改 。
(我不知道 MariaDB 是否接受了优化。)