我的网站有超过20.000.000个条目,条目有类别(FK)和标签(M2M).至于查询,即使像SELECT id FROM table ORDER BY id LIMIT 1000000, 10MySQL需要扫描1000010行,但这实在是慢得令人无法接受(而pks,索引,连接等等在这里帮助不大,仍然是1000010行).所以我试图通过使用这样的触发器存储行计数和行号来加速分页:
DELIMITER //
CREATE TRIGGER @trigger_name
AFTER INSERT
ON entry_table FOR EACH ROW
BEGIN
    UPDATE category_table SET row_count = (@rc := row_count + 1)
    WHERE id = NEW.category_id;
    NEW.row_number_in_category = @rc;
END //
然后我可以简单地说:
SELECT * 
FROM entry_table 
WHERE row_number_in_category > 10 
ORDER BY row_number_in_category 
LIMIT 10
(现在只扫描了10行,因此选择速度非常快,虽然插入速度较慢,但与选择相比它们很少见,所以没关系)
这是一个糟糕的方法,还有什么好的选择吗?
虽然我喜欢问题中的解决方案。如果 Entry_table 中的数据发生更改(可能会随着时间的推移被删除或分配给不同的类别),则可能会出现一些问题。
它还限制了数据排序的方式,该方法假设数据仅按插入顺序排序。涵盖多种排序方法需要额外的触发器和汇总数据。
分页的一种替代方法是传入要排序/分页的字段的偏移量,而不是传递给 limit 参数的偏移量。
而不是这个:
SELECT id FROM table ORDER BY id LIMIT 1000000, 10
执行此操作 - 假设在此场景中最后查看的结果的 ID 为 1000000。
SELECT id FROM table WHERE id > 1000000 ORDER BY id LIMIT 0, 10
通过跟踪分页的偏移量,可以将其传递给后续的数据查询,并避免数据库对永远不会成为最终结果一部分的行进行排序。
如果您确实只需要 2000 万行中的 10 行,您可以进一步猜测接下来的 10 个匹配行将出现在接下来的 1000 个总体结果中。如果情况并非如此,也许可以通过某种逻辑以更大的容差重复查询。
SELECT id FROM table WHERE id BETWEEN 1000000 AND 1001000 ORDER BY id LIMIT 0, 10
这应该会快得多,因为排序可能能够限制单次传递的结果。
| 归档时间: | 
 | 
| 查看次数: | 200 次 | 
| 最近记录: |