时间轴翻页本质是倒序分页,需用ORDER BY created_at DESC, id DESC+复合索引避免漂移,推荐游标分页(WHERE (created_at,id) < (?,?))替代OFFSET,前端用has_more和cursor传递,精度须匹配数据库毫秒级。

时间轴翻页的本质是倒序分页,不是视觉美化
PHP 里没有现成的 time_axis_paginate() 函数——所谓“时间轴翻页”,只是把数据按时间倒序(ORDER BY created_at DESC)后,用常规分页逻辑取第 N 页。关键在数据组织方式,不在前端样式。如果你发现翻页后内容重复、跳页或漏掉最新几条,大概率是分页逻辑没对齐时间排序和偏移计算。
用 OFFSET 实现时必须固定排序字段且加索引
常见错误是只写 ORDER BY created_at DESC,但 created_at 可能重复(尤其高并发写入),导致同一页内顺序不一致,翻页时数据漂移。解决办法:
- 排序必须包含唯一字段兜底,例如:
ORDER BY created_at DESC, id DESC -
created_at字段必须有复合索引,如:INDEX(created_at, id),否则OFFSET越大越慢 - 避免用
LIMIT 20 OFFSET 2000这类深分页,100 页之后性能断崖下跌
游标分页(Cursor-based)更适合时间轴场景
比 OFFSET 更可靠:每次请求带上次最后一条的 created_at 和 id,查询“更早”的记录。这样无跳页、无重复、无性能衰减。
示例 SQL(获取下一页):
立即学习“PHP免费学习笔记(深入)”;
SELECT * FROM posts WHERE (created_at, id) < (?, ?) ORDER BY created_at DESC, id DESC LIMIT 20
注意点:
- 参数顺序必须和
ORDER BY严格一致,否则索引失效 - PHP 中拼游标值要用
sprintf('"%s",%d', $last_created_at, $last_id)防止类型隐式转换出错 - 首次请求没有游标,用
WHERE 1或直接省略WHERE条件
前端渲染时别混淆“页码”和“时间位置”
时间轴翻页通常不显示传统页码(第 1 页、第 2 页),而是“加载更多”或“上一页(2024-03-15 之前)”。这意味着:
- 后端接口不应返回
total_pages,而应返回has_more布尔值 - 不要在 URL 里暴露
?page=5,改用?cursor=2024-03-15T08:23:11Z,12345 - 如果真要支持跳转某天,得单独建时间分区表或用
WHERE created_at < '2024-03-01'+ 游标组合,不能靠页码换算
时间轴翻页最易被忽略的点:游标值必须用数据库原生精度(比如 MySQL 的 DATETIME(3)),PHP 中用 date('Y-m-d\TH:i:s.v\Z') 生成,别用 strtotime() 再格式化——毫秒级差异会导致漏数据。



















