时间戳最适合作为索引字段的时间表示形式,需存为INT/BIGINT类型、避免函数运算、统一毫秒精度并确保查询与索引结构对齐。

时间戳本身不是“最佳索引”,而是**最适合作为索引字段的时间表示形式**——前提是它被正确存储、类型匹配、且查询方式与索引结构对齐。
时间戳字段必须是整数类型才能高效走索引
MySQL 中 TIMESTAMP 或 DATETIME 类型字段可以建索引,但真正发挥排序/范围查询优势的,是把时间存成 INT 或 BIGINT 的 Unix 时间戳(秒级或毫秒级)。原因很直接:
-
TIMESTAMP类型在 MySQL 内部仍需做时区转换和格式解析,尤其跨会话时区不一致时,WHERE created_at >= 1716511348这类查询可能意外失效 -
INT字段索引 B+ 树节点更紧凑,相同页能存更多键值,范围扫描(如WHERE ts BETWEEN 1716511348 AND 1716597748)IO 更少 - PHP 中用
time()或microtime(true)生成的数值,直接插入INT字段零转换,无隐式类型强转风险
PHP 排序前先确认时间戳精度是否一致
秒级时间戳在 PHP 数组里排序没问题,但一旦涉及数据库比对或并发写入,就容易出乱序。典型现象是:usort($logs, fn($a, $b) => $b['ts'] $a['ts']) 看似正确,可如果部分 ts 来自 time()(秒级),部分来自 round(microtime(true) * 1000)(毫秒级),数值大小已不可比。
- 统一用毫秒:PHP 侧始终用
(int)(microtime(true) * 1000),MySQL 字段设为BIGINT - 避免混用:不要把
date('U')(秒)和strtotime('2026-05-24')(也是秒)跟毫秒值放在同一数组里排序 - 数据库排序优先:能用
ORDER BY ts DESC就别在 PHP 里usort(),尤其是数据量 > 1000 行时
索引失效的三个高发场景
即使你用了 BIGINT 存时间戳、也加了索引,以下写法照样让索引失效:
立即学习“PHP免费学习笔记(深入)”;
- 在 WHERE 条件里对字段做函数运算:
WHERE FROM_UNIXTIME(ts) >= '2026-05-24'→ 改成WHERE ts >= UNIX_TIMESTAMP('2026-05-24') - 类型不匹配:
WHERE ts = '1716511348'(字符串)→ PHP 绑定参数时务必用(int)强转,或 PDO 设置PDO::ATTR_EMULATE_PREPARES = false - 联合索引顺序错位:比如建了
INDEX idx_uid_ts (user_id, ts),却只查WHERE ts BETWEEN ...,那这个索引完全用不上
真正卡住人的,往往不是“要不要用时间戳”,而是“时间戳存哪、怎么查、谁来负责精度对齐”。数据库层索引 + PHP 层类型洁癖 + 查询语句不碰函数,三者缺一不可。



















