我有一组连续的行,我想基于它们的主键(一个自动递增的整数)来获取它们。假设没有缺口,下面两种方式之间有任何性能差异吗:
SELECT * FROM `theTable` WHERE `id` IN (n, ... nk);
并且:
SELECT * FROM `theTable` WHERE `id` BETWEEN n AND nk;
我有一组连续的行,我想基于它们的主键(一个自动递增的整数)来获取它们。假设没有缺口,下面两种方式之间有任何性能差异吗:
SELECT * FROM `theTable` WHERE `id` IN (n, ... nk);
并且:
SELECT * FROM `theTable` WHERE `id` BETWEEN n AND nk;
BETWEEN
(在这种情况下)应该优于IN
,特别是当 n
增长且统计数据仍然准确时,请确保测量并检查执行计划!假设:
m
是您的表的大小n
是您要查询的范围大小n
与 m
相比较小)理论上,BETWEEN
可以使用主键索引进行单个 "范围扫描" (Oracle 术语),然后遍历最多 n
个索引叶节点。复杂度将为 O(n + log m)
IN
通常被实现为对主键索引进行一系列(循环)n
次 "范围扫描"。随着表的大小 m
增加,复杂度将始终为 O(n * log m)
... 这总是更差的(对于非常小的表 m
或非常小的范围 n
,可以忽略不计)。
n
是 m
的显着部分)无论如何,您都会获得全表扫描并计算每行的谓词:
BETWEEN
需要计算两个谓词:一个是下限,另一个是上限。复杂度为 O(m)
IN
需要计算最多 n
个谓词。复杂度为 O(m * n)
... 再次更糟,并且如果数据库可以将 IN
列表优化为哈希表而不是谓词列表,则可能为 O(m)
。
IN
列表只有1-2个元素,我有点怀疑你的说法是否正确。 - Lukas Edera between b and c
是一个宏,它会被扩展为b <= a and a <= c
。
a in (b,c,d)
是一个宏,它会被扩展为a=b or a=c or a=d
。
假设您的n
和nk
都是整数,两个表达式最终应该意义相同。使用between
变体应该更快,因为它只需要进行两次比较,而in
变体需要进行nk - n
次比较。
IN
可能会更快。了解最佳方法是在你特定情况下对两个选项进行基准测试。 - Code Commandera in (b,c,d)
是一个宏,它展开为 a = any(b,c,d)
(参见 SQL-92 标准). - eciSELECT * FROM PLAYERS WHERE SCORE BETWEEN 10 TO 20
查询2:SELECT * FROM PLAYERS WHERE SCORE IN (10,11,...,20)
在执行时间上,这两个查询都像Andomar所说的那样被翻译。