之前一直用的 SQL Server,没碰到过这个问题。换到 PostgreSQL 之后,客户反馈查询列表的时候数据顺序老是变。翻了一下代码,查询是按 CreateTime 排序的,但有几行数据的创建时间一模一样,结果每次查出来的先后顺序都不一样。

为什么 PostgreSQL 会乱

PostgreSQL 存数据的时候是哪儿有空位就塞哪儿,像往抽屉里随手丢东西。

而且你改了一行数据,PostgreSQL 不会在原来的位置改,而是找个新空位写一份新的,旧的等后台程序来清理。清理完腾出来的空位又会被别的数据占上。

所以数据的物理位置一直在变,碰到排序值一样的行,顺序就不固定了。

为什么 SQL Server 没这个问题

严格来说 SQL Server 也没保证,但实际上你基本碰不到。

SQL Server 的数据在磁盘上是按主键排好队存的,像书架上的书按编号摆整齐。你按创建时间查,碰到时间一样的,它顺着书架从左往右拿,每次拿的顺序都一样。

结论

ORDER BY 的列如果有重复值,PostgreSQL 不保证这些重复行的顺序。加一个唯一列兜底就行了:

-- 之前
SELECT * FROM records ORDER BY create_time DESC;

-- 改成
SELECT * FROM records ORDER BY create_time DESC, id DESC;

养成习惯,ORDER BY 后面永远带上主键兜底就行了。