有哪些用于复杂查询数据集分页的策略?由于count(*)需要约1.5秒,因此我们不希望每次页面查看都访问数据库。当前查询返回了大约45k行。
以下是我考虑过的一些方法:
- 缓存行数并每X分钟更新一次
- 将计数的行限制(和偏移)为41(例如),并将页面选择器显示为“1 2 3 4 ...”,然后如果有人实际转到第4页,则重新计算并显示“... 3 4 5 6 7 ...”
- 获取行数一次并将其存储在用户的会话中
- 去掉页面选择器,只有一个“下一页”链接
有哪些用于复杂查询数据集分页的策略?由于count(*)需要约1.5秒,因此我们不希望每次页面查看都访问数据库。当前查询返回了大约45k行。
以下是我考虑过的一些方法:
我曾经为一个每天浏览量超过一百万的网站,使用PHP和MySQL工程化了几个分页策略。我分阶段执行以下策略:
多列索引在尝试物化视图之前,我应该首先使用这个策略。
生成物化视图。我创建了一个定时任务,对我正在使用的文档表进行常见的反规范化处理。我会 SELECT ... INTO OUTFILE ...
然后创建新表,并将其轮换进来:
SELECT ... INTO OUTFILE '/tmp/ondeck.txt' FROM mytable ...;
CREATE TABLE ondeck_mytable LIKE mytable;
LOAD DATA INFILE '/tmp/ondeck.txt' INTO TABLE ondeck_mytable...;
DROP TABLE IF EXISTS dugout_mytable;
RENAME TABLE atbat_mytable TO dugout_mytable, ondeck_mytable TO atbat_mytable;
我的建议是在每个查询中向MySQL请求比您实际需要的多1行,根据结果集中的行数决定是否显示 下一页
链接。
MySQL
在优化 LIMIT
查询方面做得相当不错。
这意味着它会选择适当的联接缓冲区、文件排序缓冲区等,足以满足 LIMIT
语句的要求。
此外,请注意,在有 45k
行数据时,您可能不需要精确计数。可以使用针对索引字段的单独查询来确定近似计数。例如,以下查询:
SELECT COUNT(*)
FROM mytable
WHERE col1 = :myvalue
AND col2 = :othervalue
可以用这个进行近似:
SELECT COUNT(*) *
(
SELECT COUNT(*)
FROM mytable
) / 1000
FROM (
SELECT 1
FROM mytable
WHERE col1 = :myvalue
AND col2 = :othervalue
LIMIT 1000
)
使用MyISAM
会更加高效。
如果您提供一个复杂查询的示例,我可能可以更明确地说明如何改进其分页。
我绝不是MySQL专家,但也许放弃COUNT(*),改用COUNT(id)会更好?