存储行数和行数以加快分页是不是一个坏主意?

Bob*_*Bob 5 mysql pagination

我的网站有超过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 //
Run Code Online (Sandbox Code Playgroud)

然后我可以简单地说:

SELECT * 
FROM entry_table 
WHERE row_number_in_category > 10 
ORDER BY row_number_in_category 
LIMIT 10
Run Code Online (Sandbox Code Playgroud)

(现在只扫描了10行,因此选择速度非常快,虽然插入速度较慢,但​​与选择相比它们很少见,所以没关系)

这是一个糟糕的方法,还有什么好的选择吗?

Ste*_* E. 1

虽然我喜欢问题中的解决方案。如果 Entry_table 中的数据发生更改(可能会随着时间的推移被删除或分配给不同的类别),则可能会出现一些问题。

它还限制了数据排序的方式,该方法假设数据仅按插入顺序排序。涵盖多种排序方法需要额外的触发器和汇总数据。

分页的一种替代方法是传入要排序/分页的字段的偏移量,而不是传递给 limit 参数的偏移量。

而不是这个:

SELECT id FROM table ORDER BY id LIMIT 1000000, 10
Run Code Online (Sandbox Code Playgroud)

执行此操作 - 假设在此场景中最后查看的结果的 ID 为 1000000。

SELECT id FROM table WHERE id > 1000000 ORDER BY id LIMIT 0, 10
Run Code Online (Sandbox Code Playgroud)

通过跟踪分页的偏移量,可以将其传递给后续的数据查询,并避免数据库对永远不会成为最终结果一部分的行进行排序。

如果您确实只需要 2000 万行中的 10 行,您可以进一步猜测接下来的 10 个匹配行将出现在接下来的 1000 个总体结果中。如果情况并非如此,也许可以通过某种逻辑以更大的容差重复查询。

SELECT id FROM table WHERE id BETWEEN 1000000 AND 1001000 ORDER BY id LIMIT 0, 10
Run Code Online (Sandbox Code Playgroud)

这应该会快得多,因为排序可能能够限制单次传递的结果。