← 返回题目列表

可扩展字段如何设计?EAV、JSON 字段和扩展表怎么选?

高频 中等 第 5 / 33 题 更新于 2026/07/29
数据库设计扩展字段JSONEAV

简化版

可扩展字段不能一上来就把所有属性塞进 JSON。稳定、常查询、需要约束的字段应做成普通列;变化多但弱查询的属性可以放 JSON;需要强动态属性、可配置表单时可用扩展表或 EAV,但要接受查询复杂和约束变弱的代价。

详细版

常见方案有三类:

  • 普通列:适合核心字段,查询和约束最好。
  • JSON 字段:适合扩展信息、低频查询、结构变化快的属性。
  • 扩展表/EAV:适合字段由用户配置、属性集合高度动态的场景。

选择标准:

  • 是否经常作为查询条件。
  • 是否需要唯一、非空、外键、范围等约束。
  • 是否参与排序、聚合和报表。
  • 字段变化频率有多高。
  • 数据质量是否比灵活性更重要。

面试回答要强调:核心字段列化,扩展字段灰度放开,不能为了灵活牺牲所有约束。

完整版教学

一、可扩展字段是在灵活性和治理之间取舍

业务早期经常说“字段以后可能会变”,于是想把所有东西放到 JSON 或扩展表里。这样短期不用改表,长期却可能让查询、约束、统计和数据质量变得很差。

数据库表结构的价值不只是存储,还包括类型、约束、索引和可理解性。字段越核心,越应该显式建模。

记忆钩子:扩展字段不是偷懒字段。越核心、越常查、越要约束,越应该列化。

二、普通列适合稳定核心字段

普通列是默认方案。用户手机号、订单金额、支付状态、创建时间这类字段稳定、常查、需要索引或约束,就应该做成列。

create table orders (
  id bigint primary key,
  user_id bigint not null,
  amount decimal(18,2) not null,
  status varchar(32) not null,
  created_at timestamp not null
);

普通列的优势是查询清晰、约束强、索引成熟、统计方便。缺点是变更字段需要 DDL,但对核心业务来说,这个代价通常值得。

如果一个字段会出现在列表筛选、排序、报表或唯一校验里,把它放 JSON 里往往是后患。

三、JSON 字段适合弱查询扩展信息

JSON 字段适合保存不稳定、低频使用、展示型或透传型信息。例如设备扩展参数、第三方回调原始信息、非核心配置。

extra json not null

它的好处是结构灵活,新增属性不用改表。代价是类型约束弱,跨数据库兼容性差,复杂查询和索引需要额外设计。

字段特点是否适合 JSON
只展示,不筛选适合
低频排查使用适合
高频过滤排序不适合
需要唯一约束不适合
结构经常变化较适合

很多数据库支持 JSON 索引,但这不代表可以滥用。JSON 索引通常比普通列更难维护和排查。

四、扩展表适合属性集合动态但仍想结构化

扩展表是把主表核心字段和扩展属性拆开。例如商品基础表保存核心字段,商品属性表保存颜色、尺码、材质等动态属性。

product(id, name, category_id)
product_attr(product_id, attr_code, attr_value)

这种设计比 JSON 更结构化,可以对 attr_code 建索引,也方便按属性查询。但它会让 SQL 复杂,多个属性组合查询可能需要多次 join 或聚合。

如果每个品类属性不同,比如手机有内存、衣服有尺码,扩展表比较常见。如果所有商品都有价格、库存、状态,这些仍应放普通列。

五、EAV 模型灵活但代价很高

EAV 是 Entity-Attribute-Value,把所有属性都拆成实体、属性名、属性值三元组。它非常灵活,但会牺牲类型约束和查询性能。

entity_id | attr_name | attr_value
1001      | color     | red
1001      | size      | XL

如果要查“颜色为红色且尺码为 XL 的商品”,可能要对同一张属性表 join 两次。属性越多,查询越复杂。

EAV 适合可配置表单、低频后台查询、属性极不稳定的场景。不适合核心交易链路和强报表分析。

六、可以采用核心列加扩展字段的混合设计

实际工程里最稳的是混合方案:核心字段列化,扩展字段用 JSON 或扩展表。这样既保留核心查询性能,也给非核心属性留空间。

主表普通列:id, tenant_id, status, amount, created_at
JSON extra:展示扩展、第三方原始字段、灰度字段
扩展表:需要配置化查询的动态属性

一个字段如果从 JSON 里逐渐变成高频筛选条件,就应该迁移成普通列。字段设计不是一次性决定,也可以随着业务成熟演进。

七、常见误区与追问

  • 误区:为了灵活,所有字段都放 JSON。 核心字段会失去类型约束、普通索引和清晰查询,后续维护成本很高。
  • 误区:EAV 能解决所有扩展需求。 EAV 查询复杂、类型弱、性能难控,只适合属性高度动态的场景。
  • 误区:JSON 字段不用设计。 JSON 内部也需要 schema 约定、版本兼容和索引策略。
  • 追问:什么字段应该列化? 高频查询、排序、聚合、唯一校验、权限判断、金额状态等核心字段应列化。
  • 追问:JSON 字段怎么建索引? 取决于数据库能力,可用表达式索引、生成列或 JSON 专用索引,但要谨慎评估维护成本。
  • 追问:扩展属性怎么做数据质量控制? 属性元数据表定义类型、是否必填、枚举范围,再由应用层校验。

八、面试中可以这样落地

以商品系统为例:商品主表保存名称、类目、价格、库存、状态;不同类目的动态属性放扩展表;第三方透传信息放 JSON。

create table product_attr (
  product_id bigint not null,
  attr_code varchar(64) not null,
  attr_value varchar(512) not null,
  primary key (product_id, attr_code),
  index idx_attr_query (attr_code, attr_value)
);

如果某个属性变成高频筛选,比如品牌或颜色,可以单独列化或建专门索引。这样回答体现了演进思维。

九、加强记忆

扩展字段设计记住一句判断链:常查列化,弱查 JSON,强动态扩展表,极动态才考虑 EAV。灵活性不是免费午餐,代价会体现在约束、索引、SQL 复杂度和数据质量上。面试时一定要讲“什么时候从扩展字段迁移成普通列”。