<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>雪花 ID on 牛哥聊技术</title><link>https://www.lingcoder.com/tags/%E9%9B%AA%E8%8A%B1-id/</link><description>Recent content in 雪花 ID on 牛哥聊技术</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Tue, 25 Nov 2025 15:30:00 +0800</lastBuildDate><atom:link href="https://www.lingcoder.com/tags/%E9%9B%AA%E8%8A%B1-id/index.xml" rel="self" type="application/rss+xml"/><item><title>逻辑主键还是业务主键？数据库主键设计的取舍与最佳实践</title><link>https://www.lingcoder.com/p/logical-vs-business-primary-key/</link><pubDate>Tue, 25 Nov 2025 15:30:00 +0800</pubDate><guid>https://www.lingcoder.com/p/logical-vs-business-primary-key/</guid><description>&lt;img src="https://www.lingcoder.com/p/logical-vs-business-primary-key/cover.svg" alt="Featured image of post 逻辑主键还是业务主键？数据库主键设计的取舍与最佳实践" /&gt;&lt;h2 id="写在前面"&gt;&lt;a href="#%e5%86%99%e5%9c%a8%e5%89%8d%e9%9d%a2" class="header-anchor"&gt;&lt;/a&gt;写在前面
&lt;/h2&gt;&lt;p&gt;数据库主键看似简单——但选错了能让一个表&amp;quot;永远改不动&amp;quot;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;业务编码当主键 → 业务规则一变全表 rebuild&lt;/li&gt;
&lt;li&gt;UUID 当主键 → 索引性能差、空间膨胀&lt;/li&gt;
&lt;li&gt;自增 ID → 跨库迁移血泪&lt;/li&gt;
&lt;li&gt;雪花 ID → 时钟回拨能让你怀疑人生&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;新人常困惑——&lt;strong&gt;到底该选哪个&lt;/strong&gt;？本文讲清五种主流方案（自增 BIGINT、UUID v4、UUID v7、雪花 ID、业务键作主键）的优劣、取舍、典型场景。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一概念先分清逻辑主键-vs-业务主键"&gt;&lt;a href="#%e4%b8%80%e6%a6%82%e5%bf%b5%e5%85%88%e5%88%86%e6%b8%85%e9%80%bb%e8%be%91%e4%b8%bb%e9%94%ae-vs-%e4%b8%9a%e5%8a%a1%e4%b8%bb%e9%94%ae" class="header-anchor"&gt;&lt;/a&gt;一、概念先分清：逻辑主键 vs 业务主键
&lt;/h2&gt;&lt;h3 id="逻辑主键"&gt;&lt;a href="#%e9%80%bb%e8%be%91%e4%b8%bb%e9%94%ae" class="header-anchor"&gt;&lt;/a&gt;逻辑主键
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;和业务无关的&amp;quot;内部标识&amp;quot;&lt;/strong&gt;——纯技术存在。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自增 BIGINT&lt;/li&gt;
&lt;li&gt;UUID&lt;/li&gt;
&lt;li&gt;雪花 ID&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特点：&lt;strong&gt;业务永远改不到它&lt;/strong&gt;，因为它没有业务含义。&lt;/p&gt;
&lt;h3 id="业务主键"&gt;&lt;a href="#%e4%b8%9a%e5%8a%a1%e4%b8%bb%e9%94%ae" class="header-anchor"&gt;&lt;/a&gt;业务主键
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;业务上有意义的字段&lt;/strong&gt;——天然唯一。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户表用 &lt;code&gt;username&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;订单表用 &lt;code&gt;order_no&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;商品表用 &lt;code&gt;sku_code&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特点：业务可能要求改格式、改前缀、改长度。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这两个概念是冲突的&lt;/strong&gt;——主键应该用哪一种？答案不是非黑即白。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="二五种主流方案"&gt;&lt;a href="#%e4%ba%8c%e4%ba%94%e7%a7%8d%e4%b8%bb%e6%b5%81%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;二、五种主流方案
&lt;/h2&gt;&lt;h3 id="方案-1自增-bigint-逻辑主键推荐默认"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-1%e8%87%aa%e5%a2%9e-bigint-%e9%80%bb%e8%be%91%e4%b8%bb%e9%94%ae%e6%8e%a8%e8%8d%90%e9%bb%98%e8%ae%a4" class="header-anchor"&gt;&lt;/a&gt;方案 1：自增 BIGINT 逻辑主键（推荐默认）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;BIGINT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;写入性能极好&lt;/strong&gt;——InnoDB 按主键聚簇，递增 ID 永远 append&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;索引体积小&lt;/strong&gt;——8 字节&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JOIN 高效&lt;/strong&gt;——整数比较快&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;业务编码可以单独建索引、独立演化&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;跨库迁移痛&lt;/strong&gt;——两库的自增 ID 必然冲突&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;单库瓶颈&lt;/strong&gt;——发号依赖单一数据库&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;暴露业务规模&lt;/strong&gt;——&lt;code&gt;id=1234567&lt;/code&gt; 攻击者能猜测总量&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不适合分布式场景&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;适用&lt;/strong&gt;：单库或简单分库（按业务键分库）的小到中型项目。&lt;strong&gt;80% 的业务表用这个&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="方案-2uuid"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-2uuid" class="header-anchor"&gt;&lt;/a&gt;方案 2：UUID
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;BINARY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全球唯一——零中心化&lt;/li&gt;
&lt;li&gt;跨库无冲突&lt;/li&gt;
&lt;li&gt;不暴露业务规模&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;写入性能差&lt;/strong&gt;——UUID 无序，每次插入都可能引发页分裂&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;空间大&lt;/strong&gt;——16 字节，char(36) 文本形式更是 36 字节&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;索引差&lt;/strong&gt;——B+ Tree 上散列严重&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JOIN 慢&lt;/strong&gt;——字符串比较开销大&lt;/li&gt;
&lt;/ul&gt;

 &lt;blockquote&gt;
 &lt;p&gt;用 UUID 一定要 &lt;code&gt;BINARY(16)&lt;/code&gt; 不能 &lt;code&gt;CHAR(36)&lt;/code&gt;——16 字节 vs 36 字符，索引和 JOIN 性能差距巨大。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;适用&lt;/strong&gt;：&lt;strong&gt;离线生成 ID 的场景&lt;/strong&gt;（移动端先生成、再上传）、对中心化发号有强烈反感的场景。&lt;strong&gt;多数 Web 业务不推荐&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="方案-3uuid-v7时间有序-uuid"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-3uuid-v7%e6%97%b6%e9%97%b4%e6%9c%89%e5%ba%8f-uuid" class="header-anchor"&gt;&lt;/a&gt;方案 3：UUID v7（时间有序 UUID）
&lt;/h3&gt;&lt;p&gt;UUID v7（2024 RFC 9562 标准）解决了 UUID 的写入性能问题——&lt;strong&gt;前 48 位是毫秒时间戳&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;018D2DA1-7000-7XXX-XXXX-XXXXXXXXXXXX
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;时间递增——索引友好&lt;/li&gt;
&lt;li&gt;全球唯一——分布式无冲突&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;仍然 16 字节，比 BIGINT 大&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;会暴露生成时间（精确到毫秒）&lt;/strong&gt;——和雪花 ID 一样，敏感场景需评估&lt;/li&gt;
&lt;li&gt;工具/框架支持还在普及中&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;这是 2024 后比 v4 更值得用的 UUID 形式&lt;/strong&gt;——多数语言库已经支持。&lt;/p&gt;
&lt;h3 id="方案-4雪花-idsnowflake"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-4%e9%9b%aa%e8%8a%b1-idsnowflake" class="header-anchor"&gt;&lt;/a&gt;方案 4：雪花 ID（Snowflake）
&lt;/h3&gt;&lt;p&gt;Twitter 设计的分布式 ID 算法——64 位结构：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| 1 bit | 41 bits | 10 bits | 12 bits |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;| 符号 | 时间戳（毫秒） | 工作机器 ID（5 bit dc + 5 bit machine） | 序列号 |
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;10 bit 机器位 Twitter 原版就拆成 5 bit datacenter + 5 bit worker，最多支持 32 个数据中心 × 32 台机器 = 1024 节点。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;64 位 BIGINT——和自增 ID 一样紧凑&lt;/li&gt;
&lt;li&gt;时间递增——索引友好&lt;/li&gt;
&lt;li&gt;分布式无中心&lt;/li&gt;
&lt;li&gt;高吞吐（每节点每毫秒 4096 个）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;时钟回拨问题&lt;/strong&gt;——服务器时钟跳回会重复 ID&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;机器 ID 分配&lt;/strong&gt;——上千节点时管理麻烦&lt;/li&gt;
&lt;li&gt;还是暴露业务速率（每毫秒能生成多少）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;适用&lt;/strong&gt;：&lt;strong&gt;分布式系统的标准选择&lt;/strong&gt;。美团 Leaf、百度 UidGenerator 都是改进版。&lt;/p&gt;
&lt;h3 id="方案-5业务键作主键不推荐"&gt;&lt;a href="#%e6%96%b9%e6%a1%88-5%e4%b8%9a%e5%8a%a1%e9%94%ae%e4%bd%9c%e4%b8%bb%e9%94%ae%e4%b8%8d%e6%8e%a8%e8%8d%90" class="header-anchor"&gt;&lt;/a&gt;方案 5：业务键作主键（不推荐）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表自描述&lt;/li&gt;
&lt;li&gt;少一个字段&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;业务规则一变就完蛋&lt;/strong&gt;（比如 username 长度要扩展）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VARCHAR 主键聚簇索引大、慢&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关联表的外键也要 VARCHAR&lt;/strong&gt;——空间和性能双爆炸&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;业务编码可能为空&lt;/strong&gt;（早期数据没填）→ 主键不能为空 → 全表数据迁移&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;多数 OLTP 场景都不推荐这么做&lt;/strong&gt;——除非表很小且业务键真正稳定不变。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="三决策树"&gt;&lt;a href="#%e4%b8%89%e5%86%b3%e7%ad%96%e6%a0%91" class="header-anchor"&gt;&lt;/a&gt;三、决策树
&lt;/h2&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TD
 Start([单库还是分布式?])
 Start --&gt;|单库| Small{规模小?}
 Start --&gt;|分布式| Snow[雪花 ID 或 UUID v7]
 Small --&gt;|是| Auto[自增 BIGINT]
 Small --&gt;|否，将来要分库| Snow&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;90% 的场景按这个流程决定&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;小型系统、单库&lt;/strong&gt; → 自增 BIGINT&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可能分库或一开始就分布式&lt;/strong&gt; → 雪花 ID&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;离线生成 / 强分布式无中心&lt;/strong&gt; → UUID v7&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="四生产级雪花-id-的实现要点"&gt;&lt;a href="#%e5%9b%9b%e7%94%9f%e4%ba%a7%e7%ba%a7%e9%9b%aa%e8%8a%b1-id-%e7%9a%84%e5%ae%9e%e7%8e%b0%e8%a6%81%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;四、生产级雪花 ID 的实现要点
&lt;/h2&gt;&lt;p&gt;朴素雪花算法在生产里有不少坑——成熟方案要解决：&lt;/p&gt;
&lt;h3 id="1-时钟回拨"&gt;&lt;a href="#1-%e6%97%b6%e9%92%9f%e5%9b%9e%e6%8b%a8" class="header-anchor"&gt;&lt;/a&gt;1. 时钟回拨
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;绝对禁止时钟跳回&lt;/strong&gt;——可能导致 ID 重复。处理方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;启动时检查时钟，跳了就拒绝启动&lt;/li&gt;
&lt;li&gt;运行时检测，跳了就&lt;strong&gt;等回到原点再发号&lt;/strong&gt;（短暂阻塞）&lt;/li&gt;
&lt;li&gt;改进版用 &lt;code&gt;bit&lt;/code&gt; 当回拨标志位&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-机器-id-分配"&gt;&lt;a href="#2-%e6%9c%ba%e5%99%a8-id-%e5%88%86%e9%85%8d" class="header-anchor"&gt;&lt;/a&gt;2. 机器 ID 分配
&lt;/h3&gt;&lt;p&gt;朴素方案要在配置文件里写死 &lt;code&gt;worker_id&lt;/code&gt;——上千节点时是地狱。生产方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ZooKeeper / etcd 自动分配&lt;/li&gt;
&lt;li&gt;进程启动时主动注册&lt;/li&gt;
&lt;li&gt;退出时主动释放&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-数据中心-id"&gt;&lt;a href="#3-%e6%95%b0%e6%8d%ae%e4%b8%ad%e5%bf%83-id" class="header-anchor"&gt;&lt;/a&gt;3. 数据中心 ID
&lt;/h3&gt;&lt;p&gt;如上所述 Twitter 原版就把 10 bit 拆成 5+5；如果你的部署只有一个 DC，可以把 datacenter 位让渡给 worker 位，扩展到 1024 台单
DC 节点。&lt;/p&gt;
&lt;h3 id="4-序列号回滚"&gt;&lt;a href="#4-%e5%ba%8f%e5%88%97%e5%8f%b7%e5%9b%9e%e6%bb%9a" class="header-anchor"&gt;&lt;/a&gt;4. 序列号回滚
&lt;/h3&gt;&lt;p&gt;朴素方案每毫秒序列号从 0 开始——&lt;strong&gt;容易在毫秒边界 burst 时浪费&lt;/strong&gt;。改进：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上一毫秒的序列号末位作为下一毫秒的起点（散列写入）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="5-实战推荐"&gt;&lt;a href="#5-%e5%ae%9e%e6%88%98%e6%8e%a8%e8%8d%90" class="header-anchor"&gt;&lt;/a&gt;5. 实战推荐
&lt;/h3&gt;&lt;p&gt;直接用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;美团 Leaf&lt;/strong&gt;：&lt;a class="link" href="https://github.com/Meituan-Dianping/Leaf" target="_blank" rel="noopener"
 &gt;github.com/Meituan-Dianping/Leaf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;百度 UidGenerator&lt;/strong&gt;：&lt;a class="link" href="https://github.com/baidu/uid-generator" target="_blank" rel="noopener"
 &gt;github.com/baidu/uid-generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不要自己手写——这些库覆盖了所有边界。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="五对外暴露的业务编码"&gt;&lt;a href="#%e4%ba%94%e5%af%b9%e5%a4%96%e6%9a%b4%e9%9c%b2%e7%9a%84%e4%b8%9a%e5%8a%a1%e7%bc%96%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;五、对外暴露的&amp;quot;业务编码&amp;quot;
&lt;/h2&gt;&lt;p&gt;无论用什么主键，&lt;strong&gt;对外暴露通常都不直接用主键&lt;/strong&gt;——而是用业务编码：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;BIGINT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;order_no&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 对外
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;order_no&lt;/code&gt; 用规则生成：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ORD202511250001234 (前缀 + 日期 + 序号)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;为什么&amp;quot;对外用 order_no、对内用 id&amp;quot;？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;对外不暴露业务规模&lt;/strong&gt;——order_no 看不出实际订单数&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;支持改格式&lt;/strong&gt;——order_no 改前缀不影响内部关联&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可读&lt;/strong&gt;——客服发&amp;quot;订单号 ORD&amp;hellip;&amp;quot;，比&amp;quot;id=12345&amp;quot;友好&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;这是国内大多数生产系统的标准姿势&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="六几个常见反模式"&gt;&lt;a href="#%e5%85%ad%e5%87%a0%e4%b8%aa%e5%b8%b8%e8%a7%81%e5%8f%8d%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;六、几个常见反模式
&lt;/h2&gt;&lt;h3 id="反模式-1业务编码当主键--加-_old-字段做迁移"&gt;&lt;a href="#%e5%8f%8d%e6%a8%a1%e5%bc%8f-1%e4%b8%9a%e5%8a%a1%e7%bc%96%e7%a0%81%e5%bd%93%e4%b8%bb%e9%94%ae--%e5%8a%a0-_old-%e5%ad%97%e6%ae%b5%e5%81%9a%e8%bf%81%e7%a7%bb" class="header-anchor"&gt;&lt;/a&gt;反模式 1：业务编码当主键 + 加 &lt;code&gt;_old&lt;/code&gt; 字段做迁移
&lt;/h3&gt;&lt;p&gt;业务规则改了 → 加 &lt;code&gt;username_old&lt;/code&gt; 字段保留老的 → 后续查询要 &lt;code&gt;WHERE username = ? OR username_old = ?&lt;/code&gt; ——&lt;strong&gt;永远的技术债&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="反模式-2uuid-用-char36"&gt;&lt;a href="#%e5%8f%8d%e6%a8%a1%e5%bc%8f-2uuid-%e7%94%a8-char36" class="header-anchor"&gt;&lt;/a&gt;反模式 2：UUID 用 char(36)
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;CHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- ❌
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;应该用 &lt;code&gt;BINARY(16)&lt;/code&gt;——空间和性能差距巨大。&lt;/p&gt;
&lt;h3 id="反模式-3自增-id-暴露给前端"&gt;&lt;a href="#%e5%8f%8d%e6%a8%a1%e5%bc%8f-3%e8%87%aa%e5%a2%9e-id-%e6%9a%b4%e9%9c%b2%e7%bb%99%e5%89%8d%e7%ab%af" class="header-anchor"&gt;&lt;/a&gt;反模式 3：自增 ID 暴露给前端
&lt;/h3&gt;&lt;p&gt;前端 URL 里 &lt;code&gt;?orderId=12345&lt;/code&gt; ——攻击者枚举可以拿到所有订单。&lt;strong&gt;用业务编码&lt;/strong&gt;或者&lt;strong&gt;对 ID 做混淆&lt;/strong&gt;（如 hashids 库）。&lt;/p&gt;
&lt;h3 id="反模式-4复合主键"&gt;&lt;a href="#%e5%8f%8d%e6%a8%a1%e5%bc%8f-4%e5%a4%8d%e5%90%88%e4%b8%bb%e9%94%ae" class="header-anchor"&gt;&lt;/a&gt;反模式 4：复合主键
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;复合主键麻烦多——外键关联痛苦、ORM 支持不好、加新维度时改表复杂。&lt;strong&gt;永远用单字段主键 + 唯一索引表达组合唯一&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="反模式-5自增--uuid-双主键"&gt;&lt;a href="#%e5%8f%8d%e6%a8%a1%e5%bc%8f-5%e8%87%aa%e5%a2%9e--uuid-%e5%8f%8c%e4%b8%bb%e9%94%ae" class="header-anchor"&gt;&lt;/a&gt;反模式 5：自增 + UUID 双主键
&lt;/h3&gt;&lt;p&gt;&amp;ldquo;我两个都要！&amp;quot;——同时维护两个 ID 维护成本高、容易产生不一致。&lt;strong&gt;单一真理来源（single source of truth）&lt;/strong&gt;——只有一个主键。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="七性能数据对比"&gt;&lt;a href="#%e4%b8%83%e6%80%a7%e8%83%bd%e6%95%b0%e6%8d%ae%e5%af%b9%e6%af%94" class="header-anchor"&gt;&lt;/a&gt;七、性能数据对比
&lt;/h2&gt;&lt;p&gt;10 亿行表，单条 INSERT 的耗时（实测大致比例）：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th style="text-align: left"&gt;&lt;/th&gt;
 &lt;th style="text-align: left"&gt;写入耗时&lt;/th&gt;
 &lt;th style="text-align: left"&gt;索引大小&lt;/th&gt;
 &lt;th style="text-align: left"&gt;JOIN 速度&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;BIGINT 自增&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1×&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;雪花 ID&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1×&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;BINARY(16) UUID v7&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1.2×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;2×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1.2×&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;BINARY(16) UUID v4&lt;/td&gt;
 &lt;td style="text-align: left"&gt;5×（页分裂严重）&lt;/td&gt;
 &lt;td style="text-align: left"&gt;2×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;1.2×&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;CHAR(36) UUID&lt;/td&gt;
 &lt;td style="text-align: left"&gt;8×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;4×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;5×&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td style="text-align: left"&gt;VARCHAR 业务键&lt;/td&gt;
 &lt;td style="text-align: left"&gt;6×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;3×&lt;/td&gt;
 &lt;td style="text-align: left"&gt;4×&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;差距在大数据量场景被无限放大。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="八实战-checklist"&gt;&lt;a href="#%e5%85%ab%e5%ae%9e%e6%88%98-checklist" class="header-anchor"&gt;&lt;/a&gt;八、实战 Checklist
&lt;/h2&gt;&lt;p&gt;设计新表时按这个清单：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;主键用 BIGINT&lt;/strong&gt; 自增 / 雪花 ID&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;业务编码加唯一索引&lt;/strong&gt; 但不当主键&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;VARCHAR 主键不允许&lt;/strong&gt;（除非超小表）&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;UUID 用 BINARY(16) + v7&lt;/strong&gt; 不要 v4 / char(36)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;关联表外键用主键 ID&lt;/strong&gt;，不要用业务编码&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;对外 API 用业务编码&lt;/strong&gt;，不暴露主键&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;重要表的业务编码生成有规则&lt;/strong&gt;（前缀 + 日期 + 序号 / hashids）&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; &lt;strong&gt;分布式场景用雪花 ID&lt;/strong&gt;，不要自己撸&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="九关于零号-id"&gt;&lt;a href="#%e4%b9%9d%e5%85%b3%e4%ba%8e%e9%9b%b6%e5%8f%b7-id" class="header-anchor"&gt;&lt;/a&gt;九、关于&amp;quot;零号 ID&amp;rdquo;
&lt;/h2&gt;&lt;p&gt;很多人争论 ID 应该从 0 还是 1 开始——&lt;strong&gt;约定俗成是从 1 开始&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;id = 0&lt;/code&gt; 在 Java / Go 里是基本类型默认值——&lt;strong&gt;容易混淆&amp;quot;未设&amp;quot; vs &amp;ldquo;设为 0&amp;rdquo;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;业务上&amp;quot;用户 0&amp;quot;听起来怪&lt;/li&gt;
&lt;li&gt;一些 ORM 把 &lt;code&gt;id = 0&lt;/code&gt; 视为&amp;quot;新对象未保存&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;让 ID 从 1 开始是最少踩坑的约定&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结
&lt;/h2&gt;&lt;p&gt;把全文压一句：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;主键应该是业务无关的、稳定的、紧凑的——业务编码独立另存，对外用编码、对内用主键。这是数据库表能长期演化的基础。&lt;/strong&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;工程纪律：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;新表默认 BIGINT 自增&lt;/strong&gt;——简单可靠&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分布式上雪花 ID&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UUID 用 v7 + BINARY(16)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;绝不用 VARCHAR 业务键作主键&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;业务编码加唯一索引 + 对外暴露&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主键不暴露给前端&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;把这些做对，你的表能跑 10 年——而不是一年后就要做&amp;quot;主键迁移&amp;quot;这种最痛的事。&lt;/p&gt;</description></item></channel></rss>