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图,是我自己项目里用过的简化版,但核心逻辑一模一样。
这张图表达的意思很明确:一个商品可以在多个仓库有库存,一个仓库也可以存放多个商品。而库存流水就是它们之间的「连接器」,记录每一次变动。我习惯把流水表设计成只追加、不更新、不删除,这样审计和追溯就非常方便。
2.3 字段类型选择
字段类型选不对,后面全是泪。我总结了几条铁律:
| 字段 | 推荐类型 | 原因 |
|---|---|---|
| 主键 (ID) | BIGINT UNSIGNED |
自增主键,支持20亿+记录,够用 |
| 业务编码 (sku_code) | VARCHAR(64) |
长度灵活,支持字母数字组合 |
| 数量 (quantity) | INT 或 DECIMAL(18,4) |
整数用INT,带小数用DECIMAL |
| 金额 | DECIMAL(18,2) |
千万别用FLOAT,精度会丢 |
| 时间 | DATETIME(3) |
精确到毫秒,方便排序和追溯 |
| 状态 | TINYINT |
0/1/2 足够,比VARCHAR省空间 |
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),按类型统计
嗯,最后说一句:索引不是越多越好。每个索引都会增加写入开销。我一般控制在每个表不超过5个索引,核心查询能覆盖就行。
好了,数据模型设计就聊到这儿。下一章咱们开始写代码,把这几张表建起来,再配上一些实用的查询语句。到时候你会发现,模型设计得越扎实,后面写代码就越顺手。
公众号:蓝海资料掘金营,微信deep3321