← 每日面试题 学习看板

订单表的主键订单ID选择int类型和varchar类型分别适

面试题/真实面试/2026/订单表的主键订单ID选择int类型和varchar类型分别适.md

订单表的主键订单ID选择int类型和varchar类型分别适

首次来源:北京万联易达 2026-01-23 一面

原题

订单表的主键订单 ID,选择 int 类型和 varchar 类型分别适用于什么场景?

完整讲解(权威版)

最后更新:2026-10-29 · 基于第 1 次作答

L1 · 30 秒速记

结论:主键推荐数值型(int/bigint)——定长、可自增、B+Tree 索引紧凑;varchar 主键适合业务可见标识(如订单号),但空间与索引膨胀、插入随机导致页分裂。 关键词:主键选型 · 自增 · 页分裂 · 聚簇索引 · 业务可见性 边界:要业务可读就用「唯一索引的订单号」而非主键;要随机不可预测就上雪花 ID 但仍是数值型。

L2 · 核心讲解

核心考点定位:面试官想确认你是否理解「主键类型直接影响 InnoDB 聚簇索引的存储布局」——主键不仅是唯一标识,还是 B+Tree 叶子节点排序键,类型选择决定插入是否顺序、页是否分裂、二级索引是否膨胀。

机制链(≥3 环):

  1. 主键类型 → 聚簇索引叶节点大小:为什么,因为 InnoDB 主键即聚簇索引,叶子存整行数据,键越大单页容纳行越少。
  2. 自增 vs 随机 → 插入位置:为什么,因为自增保证新行追加到索引末尾、顺序写;varchar/UUID 随机插入会落在页中间,触发页分裂与随机 IO。
  3. 主键大小 → 二级索引成本:为什么,因为每个二级索引叶子都存主键值,主键越大二级索引越膨胀、回表越慢。
  4. 业务可见性 → 是否放主键:为什么,因为可读 ID(订单号)有价值,但放主键会牺牲写入性能,通常放唯一索引而非主键。

证据锚点(去重 ≥10):

对比与权衡:

方案写入性能索引空间业务可读适用
BIGINT 自增最优(顺序写)最省无内部主键、无业务含义
INT 自增优省无中小规模、上限 21 亿可接受
雪花 ID较好(趋势递增)省部分可读分布式、不暴露自增
UUID差(随机写)膨胀无极少用,仅跨库合并
VARCHAR 订单号中(若有序可优化)膨胀强需业务可见标识

常见误区:

  1. 错误:主键用 UUID 最安全 → 正确:UUID 无序 + 128 位,页分裂严重、索引膨胀;用雪花/数值型 → 为什么错:只看唯一性,忽略聚簇索引布局。
  2. 错误:订单号适合直接做主键 → 正确:订单号做唯一索引,主键仍用自增数值 → 为什么错:把业务可读与存储性能混为一谈。
  3. 错误:varchar 主键不浪费空间 → 正确:变长 + 可能溢出,二级索引都带主键,放大空间 → 为什么错:忽略二级索引存储主键的放大效应。
  4. 错误:主键类型对查询没影响 → 正确:主键大小影响页内行数与二级索引大小,直接影响扫描与回表成本 → 为什么错:只看到逻辑唯一,看不到物理布局。

适用边界:若业务明确要求"订单号对外可见且需快速定位",用「自增主键 + 订单号唯一索引」;若要求不暴露自增(防竞对猜测),用雪花 ID 做主键、订单号仍可做唯一索引;若跨库/历史合并导致自增冲突,才考虑业务字符串主键并接受写入代价。

延伸追问(≥3)

  1. 为什么二级索引的叶子要存主键值?
  1. 雪花 ID 和自增主键怎么选?
  1. varchar 主键的 ROW_FORMAT=DYNAMIC 溢出意味着什么?

面试者参考回答(400–700 字)

【结论】 主键优先数值型(int/bigint)——定长、可自增、聚簇索引紧凑;varchar 主键适合业务可见标识,但会带来空间与索引膨胀、随机插入页分裂,通常放唯一索引而非主键。

【三点】 第一,存储与写入:数值主键定长、自增保证顺序追加,B+Tree 页内行数多、随机 IO 少;varchar 或 UUID 随机插入会落在页中间触发页分裂,放大缓冲池压力。第二,索引成本:InnoDB 每个二级索引叶子都存主键值,主键越大二级索引越膨胀、回表越慢,所以用 varchar 主键会放大所有索引。第三,业务可见性:如果订单号要对外可读,正确做法是"自增主键 + 订单号唯一索引",既保写入性能又保可读定位;若不想暴露自增量,用雪花 ID(数值型、趋势递增)做主键更合适。

【边界】 只有跨库合并、历史数据主键冲突,或确需字符串主键的业务,才考虑 varchar 主键并接受写入代价;一般场景别用 UUID 做主键,它无序又占 128 位,是索引布局最差的选择。

面试记录 2026-10-29(第 1 次)

题目:订单表的主键订单ID选择int类型和varchar类型分别适

难度:medium

标签:db/mysql/innodb, real-interview, difficulty/medium

评分:⭐⭐⭐⭐☆(4/5)

练习次数:1

我的回答

订单的主键id主要还是推荐使用int类型,并且推荐使用bigint类型,可以直接通过自增来完成id有序性的保证,更便于数据存储;

使用varchar类型一方面是存储空间浪费,另一方面可能造成跳跃数据,影响innodb创建索引的空间占用;

不过varchar类型的id也有自身好处,就是业务可见性,可以通过维护指定业务的标识来通过id一眼看出数据的类型,不过不推荐放在主键id上可以放在订单号上,不做主键id而是一个标识创建唯一索引就好

点评

优点:推荐 int/bigint 自增正确,varchar 的空间浪费/碎片/索引膨胀讲清,业务可见性移到订单号唯一索引的做法很到位。

不足:未对比雪花 ID、UUID 的聚簇索引影响(页分裂/随机 IO)。

补充:二级索引叶子存主键,主键越大索引越膨胀;雪花 ID 数值型趋势递增优于 UUID。

完整讲解见上方「完整讲解(权威版)」