2. 库存数据模型设计:核心实体、ER图、字段类型与索引策略

好,咱们进入第二章。数据模型设计,说白了就是给库存系统打地基。我见过太多项目,业务逻辑写得天花乱坠,结果数据库一跑就崩,根源就是模型没设计好。今天咱们就把商品、仓库、库存流水这三个核心实体彻底聊透。

2.1 核心实体:商品、仓库、库存流水

库存系统里,最绕不开的就是这三个家伙。我习惯把它们比作「人、地点、事件」——商品是谁,仓库在哪,库存流水就是发生了什么。

2.1.1 商品(Product)

商品表不只是存个名字和价格。你想想看,一个SKU可能对应多个批次,每个批次还有不同的保质期。所以商品表的核心字段,我个人建议至少包含:

  • product_id:主键,自增或雪花ID都行
  • sku_code:唯一编码,业务上靠它做关联
  • product_name:商品名称
  • category_id:分类ID,方便做统计
  • unit:计量单位,比如「件」「箱」「千克」
  • status:状态,0下架 1上架

嗯,这里要注意:sku_code一定要加唯一索引。我在项目中遇到过因为没加唯一索引,导致同一个商品被插入了两条记录,库存对账对了一整天才发现。

2.1.2 仓库(Warehouse)

仓库表相对简单,但有个坑——仓库编码。很多系统直接用ID当仓库标识,但业务上更常用的是「仓编码」,比如WH001、WH002。字段设计:

  • warehouse_id:主键
  • warehouse_code:仓库编码,唯一
  • warehouse_name:仓库名称
  • address:地址
  • type:仓库类型,比如「常温仓」「冷藏仓」
  • status:状态

我曾经踩过一个坑:仓库表没加warehouse_code的唯一索引,结果业务方在Excel导入时重复创建了同一个仓库,导致库存数据全乱了。从那以后,凡是业务编码,我必加唯一索引。

2.1.3 库存流水(Inventory Transaction)

这是整个库存系统的灵魂。每一件商品的每一次移动,都要记录在案。字段设计:

  • transaction_id:主键
  • product_id:商品ID
  • warehouse_id:仓库ID
  • batch_no:批次号,用于追溯
  • quantity:变动数量,正数入库,负数出库
  • transaction_type:类型,比如「采购入库」「销售出库」「盘点调整」
  • created_at:创建时间
  • operator:操作人

这里有个设计要点:quantity字段用有符号整数,入库为正,出库为负。这样统计库存余额时,直接SUM(quantity)就行,不用区分出入库表。我早期做过一个项目,把入库和出库分成了两张表,结果每次查余额都要做一次全表关联,性能惨不忍睹。

2.2 ER图设计

光说理论太干,咱们直接画图。下面这张ER图,是我自己项目里用过的简化版,但核心逻辑一模一样。

商品 (Product) product_id (PK) sku_code (UK) product_name category_id 仓库 (Warehouse) warehouse_id (PK) warehouse_code (UK) warehouse_name type 库存流水 (Inventory Transaction) transaction_id (PK) product_id (FK) → Product warehouse_id (FK) → Warehouse quantity, batch_no, transaction_type 1 N 1 N

这张图表达的意思很明确:一个商品可以在多个仓库有库存,一个仓库也可以存放多个商品。而库存流水就是它们之间的「连接器」,记录每一次变动。我习惯把流水表设计成只追加、不更新、不删除,这样审计和追溯就非常方便。

2.3 字段类型选择

字段类型选不对,后面全是泪。我总结了几条铁律:

字段 推荐类型 原因
主键 (ID) BIGINT UNSIGNED 自增主键,支持20亿+记录,够用
业务编码 (sku_code) VARCHAR(64) 长度灵活,支持字母数字组合
数量 (quantity) INTDECIMAL(18,4) 整数用INT,带小数用DECIMAL
金额 DECIMAL(18,2) 千万别用FLOAT,精度会丢
时间 DATETIME(3) 精确到毫秒,方便排序和追溯
状态 TINYINT 0/1/2 足够,比VARCHAR省空间
⚠️ 警告:金额字段千万别用FLOAT或DOUBLE。我曾经接手过一个项目,因为用了FLOAT,导致对账时差了0.01元,查了三天才发现是浮点精度问题。用DECIMAL,稳如老狗。

2.4 索引策略

索引这东西,加多了写慢,加少了查慢。我一般遵循「查询驱动索引」的原则——先看业务怎么查,再决定加什么索引。

2.4.1 商品表索引

  • 主键索引PRIMARY KEY (product_id)
  • 唯一索引UNIQUE INDEX idx_sku_code (sku_code)
  • 普通索引INDEX idx_category_id (category_id),方便按分类查询

2.4.2 仓库表索引

  • 主键索引PRIMARY KEY (warehouse_id)
  • 唯一索引UNIQUE INDEX idx_warehouse_code (warehouse_code)

2.4.3 库存流水表索引

这是索引设计的重头戏。流水表数据量最大,查询也最频繁。我建议:

  • 主键索引PRIMARY KEY (transaction_id)
  • 联合索引INDEX idx_product_warehouse (product_id, warehouse_id),按商品+仓库查流水
  • 时间索引INDEX idx_created_at (created_at),按时间范围查流水
  • 类型索引INDEX idx_transaction_type (transaction_type),按类型统计
💡 小技巧:如果流水表数据量超过千万级,可以考虑按时间分区。比如按月分区,查询时只扫描一个分区,性能提升非常明显。我有个项目,分区后查询时间从3秒降到了0.1秒。

嗯,最后说一句:索引不是越多越好。每个索引都会增加写入开销。我一般控制在每个表不超过5个索引,核心查询能覆盖就行。

好了,数据模型设计就聊到这儿。下一章咱们开始写代码,把这几张表建起来,再配上一些实用的查询语句。到时候你会发现,模型设计得越扎实,后面写代码就越顺手。


公众号:蓝海资料掘金营,微信deep3321