我有一组我想根据主键获取的连续行,主键是一个自动递增的整数。假设没有漏洞,之间是否有任何表现:
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)
......这总是更糟,或者O(m)
如果数据库可以将IN
列表优化为哈希图,而不是谓词列表。
a between b and c
是一个扩展为 的宏b <= a and a <= c
。
a in (b,c,d)
是一个扩展为 的宏a=b or a=c or a=d
。
假设您的n
andnk
是整数,那么两者最终的含义应该相同。between
变体应该快得多,因为它只有两次比较,而不是变体nk - n
的比较in
。
我已经针对这个问题进行了研究。我的表中有 11M 行。我对此执行了两个查询:
查询一:SELECT * FROM PLAYERS WHERE SCORE BETWEEN 10 TO 20
查询 2:SELECT * FROM PLAYERS WHERE SCORE IN (10,11,...,20)
在执行时间时,两个查询都被翻译为Andomar上面所说的。
在这两个查询中,查询 1 的运行速度比查询 2 快。
要了解更多信息,请点击此链接:
谢谢你。
在许多数据库服务器中,IN() 只是多个 OR 子句的同义词,因为两者在逻辑上是等价的。在 MySQL 中并非如此,它对 IN() 列表中的值进行排序并使用快速二进制搜索来查看值是否在列表中。这是列表大小的 O(Log n),而等效的一系列 OR 子句是列表大小的 O(n)(即,对于大型列表来说要慢得多)