我经常遇到这个用例:
我有一个队列表,需要处理大量(数百万)条记录(与远程API同步,......)。
传统上我会使用以下方法:
CREATE TABLE Queue (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
...
processed TINYINT(1) UNSIGNED NOT NULL DEFAULT 0
);
批处理过程如下:
SELECT ... FROM Queue WHERE processed = 0 LIMIT n;
UPDATE Queue SET processed = 1 WHERE id IN(...);
当按原样使用此方法时,SELECT
可能会产生全表扫描(这对于第一批可能足够快,但随着表中的第一个记录逐渐变为{{1}而变得越来越慢无论如何,processed=1
必须阅读它们。
我只能看到两个改善效果的选项:
SELECT
列索引的基数非常低(processed
)可能根本无法改善效果。
对0|1
列进行分区会使processed
非常快(假设没有使用SELECT
子句),因为它只能返回分区中的ORDER BY
个第一条记录。
然而,性能损失来自n
,它必须将记录从一个分区移动到另一个分区。
对于这个相当常见的用例,我是否错过了更好的表现方法?
答案 0 :(得分:1)
根据评论:提供主键的值可以显着加快选择。使用MySQL处理队列时,最好记住处理过的最后id
的值是什么,并将其保存在某处。在主键列上执行范围查询,例如:
SELECT ... FROM Queue WHERE id BETWEEN 10000 AND 20000 LIMIT N;
产生明显更快的结果。我没有测量任何东西,但是对于使用MySQL作为队列机制的人来说 - 上面对队列检索的修改应该会产生显着的结果。
您的里程数因自动增量等因素而异,因此在实施前应谨慎使用上述方法。