Mysql IN子句与自动增量ID的范围

Posted

技术标签:

【中文标题】Mysql IN子句与自动增量ID的范围【英文标题】:Mysql IN clause vs range for auto increment ID 【发布时间】:2015-03-11 04:48:20 【问题描述】:

我有一个大约 5000 万行的 mysql 表(预计会增长)。现在我需要遍历整个表。我正在尝试分块迭代,即获取 N 行,处理,再获取 N 行

该表具有自增整数 ID 作为主键。这将使迭代更容易。我的问题是:哪个语句会更快(循环计数器在哪里):

SELECT * FROM table WHERE ID IN (i, i+1, ..., i+N)

SELECT * FROM table WHERE ID >= i AND ID < i + N

第一个使用IN 子句,它对主键进行查找,我认为这非常快。第二个具有小于+大于条件的条件,对于非索引列将非常慢。但是由于我是在主键上做的,所以我不确定性能。

其中哪一个应该提供更好的性能,比如N = 1000

【问题讨论】:

何不亲自试一试,分析结果? 也这样做,但想知道是否有人可以对它进行一些理论上的解释...... 第二个版本。你真的应该花一点时间学习B-tree 数据结构(这是 MySQL 索引的实现方式):很明显,从这种结构中定位一个范围是 O(log n),而定位 m 个特定节点—虽然不是 *hard* — 仍然是 O(m*log n)。 【参考方案1】:

使用这个:

SELECT * FROM table WHERE ID >= $i AND ID < $i + $N

“范围扫描”很高兴找到第一行(在$i处),然后得到Next,Next,...非常高效。

但是,这确实假设 ID 是密集的。如果您删除了很多行,您可能不会每次都使用 $N 行。 (是的,你可以说这无关紧要。)

$N = 1000 -- 这是一个合理的数字 -- 您没有花费“太长时间”,也没有“阻塞”太多行。等等。

有关其他技术(例如不密集时),请参阅my blog on deleting in chunks。

【讨论】:

当然,无论密度如何,总是有一定大小的块可以使用SELECT * FROM table WHERE ID &gt;= $i LIMIT 1000,使用前一个块中的最大ID作为$i的下一个值。跨度>

以上是关于Mysql IN子句与自动增量ID的范围的主要内容,如果未能解决你的问题,请参考以下文章

mysql IN子句不使用可能的键

MySQL:开始日期和结束日期之间的日期的 IN 子句?

MySQL 视图 OR vs IN 子句

Mysql select with in 子句不使用索引

MySQL中的空IN子句参数列表

MySQL UNION SELECT 和 IN 子句