我有一组我想根据主键获取的连续行,主键是一个自动递增的整数。假设没有漏洞,之间是否有任何表现:
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。
假设您的nandnk是整数,那么两者最终的含义应该相同。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)(即,对于大型列表来说要慢得多)