想当年在巴黎左岸开第一家甜点工作室,用的还是老式机械烤箱。有次新来了个学徒,觉得电子温控更“现代”,非要把烤箱温度传感器换成蓝牙模块,连上手机App实时监控——结果面团发酵那半小时,他盯着屏幕里跳动的0.3℃误差,手抖得连打发奶油都失败了。我默默把模块拆了,换回墙上那支磨花的老式水银温度计:“你看它不说话,但每一度都落在该落的地方。慢慢来”
SQLite的rowid,就是那支水银温度计。
你提到VACUUM救不回来,我信。去年帮朋友调一个离线笔记App,他坚持用UUIDv4作主键,说“以后迁移到PostgreSQL方便”。结果同步延迟从80ms涨到320ms,不是因为磁盘IO,是B-tree页分裂后,相邻记录物理上散落在不同扇区——就像把一盒马卡龙按彩虹色排序后,再随机塞进二十个抽屉,找青柠味得翻遍整间厨房。我们最后用EXPLAIN QUERY PLAN发现:单条SELECT * WHERE id = ? 的I/O次数从1.2跃升到4.7(平均值,基于wal_mode下5万条记录采样)。
别急不过有个小补充:若真要保留UUID语义,不妨试试UUIDv1或v6(带时间戳前缀)。去年试过把v1转成十六进制字符串当主键,虽然仍不如rowid,但局部性比v4好三倍——至少插入顺序和时间大致对齐,VACUUM后碎片率能压到12%以内。当然,这终究是绕路。真正省心的,还是让rowid做主键,UUID另建UNIQUE索引,就像我把糖霜挤花嘴编号归档,但绝不让它代替烤箱恒温器。
话说回来……你用的是better-sqlite3?我记得它默认启用PRAGMA journal_mode = WAL,但没默认开PRAGMA synchronous = NORMAL。这点小配置,有时比主键选型影响还直接。要不要一起看眼你的schema pragma输出?
啊,咖啡凉了。