DBAtlas · 数据库运维图谱

决策:选择合适的数据类型

选择数据类型是日后修正代价最高的决策之一:错误的类型会导致错误的结果(例如用 float 存储金额)、空间浪费和查询缓慢。这棵决策树引导你为数值、文本、日期/时间、键(PK)、半结构化(JSON)和类别(ENUM)字段选择合适的类型,并指出金额和字符集等经典陷阱。

你要存储什么类型的数据?

合适的类型由数据的性质决定。该字段属于哪一类:数字、文本、日期/时间、表的主键、灵活/半结构化(JSON)数据,还是一组有限的类别?

  • 数值(数量、金额、测量值、计数器)
  • 文本(名称、描述、代码)
  • 日期和/或时间
  • 我正在设计主键(PK)
  • 灵活/嵌套/可变字段(半结构化数据)
  • 一组有限、已知的类别(状态、类型、优先级)

数字是整数还是小数 — 是否是金额?

对于数值,最关键的区别是精确性。该值是整数(数量、ID、计数器)还是小数?如果是小数,是否是金额/财务数值?二进制浮点数(FLOAT/DOUBLE)绝不能用于金额或任何要求精确的地方,因为它会产生舍入误差。

  • 整数(数量、计数器、id)
  • 金额或精确小数(价格、余额、比率)

建议:整数(SMALLINT / INT / BIGINT)

对于整数,选择能覆盖所需范围的最小类型。不必要的大类型会浪费空间和索引大小;但对于计数器/主键等可能增长的字段,足够的宽度对防止溢出至关重要。

建议:NUMERIC / DECIMAL — 金额绝不用 FLOAT

金额和精确小数应使用定点(精确)的 NUMERIC/DECIMAL。FLOAT/DOUBLE 是二进制浮点数,无法精确存储 0.1 这样的值;加法/乘法会产生分位漂移、错误的余额和审计问题。

建议:文本 — VARCHAR vs TEXT vs CHAR

对于文本,可变长度使用 VARCHAR/TEXT,真正固定长度使用 CHAR。在现代引擎中,VARCHAR 和 TEXT 的存储差异大多可以忽略;真正的决策在于是否施加语义上的限制(长度约束)。

建议:日期/时间 — 带时区的 TIMESTAMP

如果存储的是一个时刻(事件时间),选择具有时区感知的类型。不带时区存储会导致跨区域/夏令时变化时计算和比较出错。

建议:主键 — BIGINT vs UUID

主键有两个主要选项:递增数字(BIGINT identity/sequence)或 UUID。数字主键体积小、对索引友好,但可预测且需要集中生成;UUID 可以分布式生成,但体积更大,其随机顺序可能损害索引。

建议:JSON / JSONB — 适度使用

JSON 类型对于模式灵活、嵌套或稀疏的字段很强大;但可能会失去关系型约束(约束、索引、类型安全)。规则:将固定且频繁查询的字段放入普通列,只把真正可变的部分保留在 JSON 中。

建议:ENUM vs 查找(参照)表

对于有限的类别集合有两种选择:引擎的 ENUM 类型,或查找表 + 外键。ENUM 紧凑简单,但添加值需要模式变更;查找表灵活,并且可以携带额外属性(描述、启用标志、排序)。

在 DBAtlas 中打开 →