page contents

Python 3.14 uuid7 这个新功能救了多少新手?数据库主键再也不怕乱序了

你有没有遇到过这种情况:辛辛苦苦搭好一个后台,用户表的主键用的是 uuid4,增删改查都挺顺。直到某天产品经理说"给我拉一下最新注册的 10 个用户",你才发现自己掉坑里了。uuid4 是纯随机的,本身不带任何时间信息,想按注册先后排,只能再查一个 created_at 字段,再建一个索引。比这更隐蔽的是,随机主键会让数据库的索引像被反复插针一样,写入越久越慢,而你很难第一时间想到是主键在捣乱。

attachments-2026-07-sd6Br7Ln6a5836541a1de.png

你有没有遇到过这种情况:辛辛苦苦搭好一个后台,用户表的主键用的是 uuid4,增删改查都挺顺。直到某天产品经理说"给我拉一下最新注册的 10 个用户",你才发现自己掉坑里了。uuid4 是纯随机的,本身不带任何时间信息,想按注册先后排,只能再查一个 created_at 字段,再建一个索引。比这更隐蔽的是,随机主键会让数据库的索引像被反复插针一样,写入越久越慢,而你很难第一时间想到是主键在捣乱。说白了,uuid4 只管"不重复",不管"先后",一旦业务开始关心顺序,它就不够用了。这个问题在用户量小的时候隐身,量一大就跳出来咬人,而且往往在你最忙的上线夜。早点认识 uuid7,能少熬好几个这样的夜。

其实从 Python 3.14 开始,这事儿不用再这么折腾了。标准库悄悄多了一个新朋友:uuid7。它和 uuid4 长得几乎一样,却是"带时间戳、能排序"的那一款。今天我们就聊聊,这个新功能到底帮新手解决了什么麻烦。

一、uuid4 那两个让人头大的坑

先说第一个坑:它压根不打算让你按时间排序。

from uuid import uuid4, uuid7 

# 老写法:完全随机,顺序彻底打乱

print(uuid4())

# 新写法:前半段是时间戳,按生成先后有序

print(uuid7())

你跑出来的几行,顺序是彻底打乱的,这很正常——uuid4 的设计目标就是"随机、不重复",从来没想过让你排时间顺序。所以一旦你要"按创建先后"看数据,只能额外维护一个时间字段。

# 为了能按时间排,只能额外加一列

CREATE TABLE users (

    id   CHAR(36) PRIMARY KEY,

    name TEXT,

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP

)

# 查询时还多背一个 ORDER BY

SELECT * FROM users ORDER BY created_at DESC LIMIT 10

你看,明明只是想排个序,却要多写一行建表 SQL,多建一个索引,查询时再多背一个 ORDER BY。本来一行 uuid 就能解决的事,硬生生变成了三处负担。更要命的是,不少新手会想当然拿 uuid4 当 ORDER BY 的近似,结果翻页时顺序乱跳,还查不出毛病。

第二个坑更阴,叫索引碎片化。

数据库的主键索引一般是一棵 B 树。如果主键是递增的,比如自增 ID,新数据永远插在末尾,树又整齐又快。可 uuid4 是随机的,每一行都可能插到树中间的某个空位,索引页被反复分裂、反复写盘。想象一个书架:自增 ID 像按编号从左到右摆书,uuid4 却像把每本书随机扔进空位,书架隔三差五就得整体重排。数据量一大,插入就明显变慢,而且你很难一眼看出是主键在捣乱。更糟的是,碎片化的索引还会让"按主键范围扫"和"按二级索引回表"一起变慢,问题是连锁的。

二、uuid7 到底是什么来头

uuid7 是 RFC 9562 里定义的新版 UUID,思路特别朴素:把"生成这一刻的时间戳"直接塞进 UUID 的前半段。

它的结构可以这么理解:前面一大截是生成时刻的时间,精确到毫秒;中间是一段计数器,保证同一毫秒内生成的 UUID 也不会撞车;最后才是随机数。也就是说,它同时拿到了两样东西——"不重复"和"带时间"。以前要同时拿到这两点,你得自己拼:要么用雪花算法,要么 uuid1 再存时间,要么 uuid4 配 created_at。uuid7 一口气把两件事都办了。有人问,那直接用自增 ID 不就行了?小项目单表确实够用。可一旦分库分表,不同机器各自自增,号就撞了,又得引入雪花算法或号段分配,复杂度一下子上来。uuid7 的好处是,顺序和唯一它一手包办。

最妙的是,因为时间固定在最前面,而且长度固定,所以把 uuid7 当字符串直接排序,排出来的就是生成的时间顺序。最关键的一点:它是按时间先后生成的,天然有序。你拿 uuid7 当主键,新数据天然插在末尾,B 树不用频繁分裂,写入稳稳当当。同时它还保留了 UUID 最大的优点:分布式系统里不同的机器各生成各的,天生不重复,不用像自增 ID 那样在分库分表时去搞雪花算法或者号段分配,也不用担心不同机器发到同一个号。还有个小细节:uuid7 的 42 位计数器,足够撑住很高的并发,同一毫秒生成上百万个也不会重复,普通业务根本碰不到上限。所以别被"毫秒"两个字吓到,它稳得很。

三、怎么用,几个例子就懂

排序到底有多直观,跑一段就知道了:

from uuid import uuid4, uuid7

 

# uuid7:生成顺序就等于时间顺序,排不排一样

print(sorted([str(uuid7()) for _ in range(4)]))

 

# uuid4:排完还是乱的,因为它压根没带时间

print(sorted([str(uuid4()) for _ in range(4)]))

你看,uuid7 生成出来就已经是按时间排好的,排不排一个样;而 uuid4 排完还是乱的,因为它压根没带时间。这就是它当主键最香的地方。记住一句话:能排序的 ID,天然适合做"追加型"数据的顺序键。

把它当数据库主键,改动基本为零:

import sqlite3

from uuid import uuid7

 

con = sqlite3.connect(":memory:")

con.execute("CREATE TABLE users (id TEXT PRIMARY KEY, name TEXT)")

con.execute("INSERT INTO users VALUES (?, ?)", (str(uuid7()), "小明"))

con.execute("INSERT INTO users VALUES (?, ?)", (str(uuid7()), "小红"))

因为新数据总插在末尾,写入不会频繁触发索引重排,性能比随机主键稳得多。做用户表、订单表、日志表、消息表这类"追加为主"的表时,uuid7 尤其合适。顺带一提,因为 uuid7 末尾是随机的,它不像自增 ID 那样容易被外人猜出"你总共有多少用户""昨天注册了多少",对防遍历、防枚举也更友好。

还有个对新手特别友好的细节:uuid7 是 Python 3.14 标准库自带的,不用 pip install 任何第三方包,开箱即用。想在命令行快速造一个也行:

python -m uuid -u uuid7

注意一个安全场景:uuid7 和 uuid4 一样是"伪随机",并不是密码学安全随机。如果你的 UUID 要拿来当 token、当密钥、当会话标识用,请继续用 uuid4(官方文档明确建议:安全敏感的场景用 uuid4)。另外比起更老的 uuid1,uuid7 还顺手修掉了一个隐私隐患:uuid1 会把网卡的 MAC 地址编进 UUID,等于把机器身份泄露出去;uuid7 只用时间加随机数,不沾硬件信息,更干净。

四、顺带认识下 uuid6 和 uuid8

同一个 RFC 9562 家族里,还有两个兄弟值得知道:

from uuid import uuid6, uuid8

 

# uuid6:时间和 uuid1 类似,但放到前面,照顾数据库局部性

print(uuid6())

 

# uuid8:完全自定义,a/b/c 三个参数随你给

print(uuid8(a=12345))

uuid6 和 uuid1 思路类似,也是把时间放在前面照顾数据库局部性,但同样不泄露 MAC 地址,算是对 uuid1 的现代化替代。uuid8 则是完全自定义:a、b、c 三个参数随你给,不需要密码学安全时,你能造出完全按自己规则来的唯一 ID。另外 Python 3.14 还给 uuid 模块补了两个常量 uuid.NIL(全 0)和 uuid.MAX(全 1),做边界判断、占位、测试时挺顺手。当然也不是无脑上 uuid7。你只是做个本地小工具、单表几百条数据,自增 ID 简单直观,完全够用。uuid7 真正发光的地方,是那些要分布式生成、又要按时间查"最新"的场景。

如果拿不准,记住这张心法:单机小表,自增 ID 最省事;要全局唯一又不想引包,用 uuid4;主键要能按时间查最新、还要分布式不撞号,uuid7 直接上。把这张表存进脑子,下次建表不用再纠结。

一句话记住:要随机不重复用 uuid4,要能排序、当主键用 uuid7,要完全自定义规则用 uuid8,要照顾老数据库的局部性可以看看 uuid6。

说了这么多,你平时主键都用啥?是自增 ID、uuid4,还是早就用上 uuid7 了?你有没有因为 UUID 乱序、撞号,或者排不了序踩过坑?评论区聊聊,让更多新手少走点弯路。也欢迎已经在用的朋友,评论区说说你踩过的坑和怎么填的。

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

 

  • 发表于 2026-07-16 09:40
  • 阅读 ( 21 )
  • 分类:Python开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

2247 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. Pack 2247 文章
  3. 小柒 2228 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章