照片里藏着拍摄地点:10 种存法,只有 4 种会把它带出去
同一张照片 10 种存法,4 种把定位带出去,涂黑也白涂。
结论摆在前面:一万条以内,用一个文本文件存数据够用;可只要程序天天要去改旧记录,就得换数据库——10 万条时改一条,文件要 737 毫秒,数据库 0.2 毫秒。

我给自己的记账小工具写了个最省事的存法:所有记录塞进一个 .json 文件。JSON 就是一种纯文本格式,长得像花括号套花括号,用记事本也能打开看。
一开始只有几十条,没感觉。后来程序每记一单,都要把整个文件读出来、加一条、再整个写回去。条数一多,点保存那个圈就转起来了。
我就拿同一批数据做了对照:一边是 JSON 文件,一边是 SQLite。SQLite 是个不用装服务、整个库就是一个文件的数据库,Python 自带,不用 pip 装东西。
造了 1 千、1 万、10 万条订单,字段一样:序号、姓名、手机号、金额、日期。每种操作跑 5 次,取中位数。
| 记录条数 | JSON 改一条 | 数据库改一条 | JSON 读全部 | 数据库读全部 |
|---|---|---|---|---|
| 1,000 条 | 8.4 毫秒 | 0.3 毫秒 | 1.4 毫秒 | 1.3 毫秒 |
| 10,000 条 | 71 毫秒 | 0.2 毫秒 | 13 毫秒 | 12 毫秒 |
| 100,000 条 | 737 毫秒 | 0.2 毫秒 | 167 毫秒 | 147 毫秒 |
改一条这一列,文件那边 8.4 → 71 → 737,条数翻十倍时间也翻十倍,一路往上涨。数据库一直趴在 0.2 毫秒,快到没感觉。
读全部反而差不多:10 万条时 167 毫秒对 147 毫秒,差 20 毫秒。所以「数据库比文件快」这句话只对一半,快慢看你是改一条还是整份读。
改一条,文件这边得这么写:
with open("data.json", encoding="utf-8") as f:
rows = json.load(f) # 先把整个文件读进来
for r in rows:
if r["id"] == mid:
r["amount"] = 1.00
with open("data.json", "w", encoding="utf-8") as f:
json.dump(rows, f, ensure_ascii=False) # 再整份重写回去
数据库就两行:
c = sqlite3.connect("data.db")
c.execute("UPDATE t SET amount=1.0 WHERE id=?", (mid,))
c.commit()
commit 是把这次改动落盘的动作,只碰这一页,别的数据不动。
文件大小也差一截。10 万条时 JSON 9,569,889 字节,数据库 4,734,976 字节,差不多一半。
按名字找一个人(1 万条数据):JSON 每次都要读完整个文件,16 毫秒;数据库不建索引 1.2 毫秒,建了索引 0.3 毫秒。索引像书后面的目录,不用一页页翻,直接翻到那一页。
真正让我换掉的不是速度,是丢数据。
我写了个程序反复往文件里刷数据,半路强杀进程(kill -9,等于直接拔电源),一共杀 5 次:5 次文件全都读不出来。4 次是 0 字节,文件刚被清空还没写进去;1 次停在 1,413,120 字节,报 JSONDecodeError: Expecting ',' delimiter,半截 JSON 拼不回去了。
同样的杀法换数据库:5 次全部通过完整性检查,行数 84、86、87、88、79,数据都在。
一句话:数据库有事务(transaction),一条记录要么完整写进去,要么完全不算;文件写到一半,就真的只剩一半。
json.dump。我最早就是点一次保存重写一遍,10 万条时手一按就卡 0.7 秒。同一张照片 10 种存法,4 种把定位带出去,涂黑也白涂。
18.6 MB 字体按页面用字裁到 232.7 KB,附四个坑
同一段 63 秒视频 9 种压法实测:设得越清楚,文件越大画质没变好。