WMS“双层库存模型”设计:从多维度库存到分层管理与流水追溯
本文是我编写的电子书《跨境供应链:海外仓OTWB项目实战》第4章的第13篇文章,该电子书目前已经更新完成,已经有接近900人购买订阅。
部分关键内容会设置为付费阅读,还有部分内容会免费更新在微信公众号上。如果想要获得更完整的、体系化的知识,建议私聊我付费订阅全文,目前的价格是¥108
,知识星球的成员可以获得5折的优惠,仅需¥54
即可加入。更多详情,欢迎加我的微信(vitamin_mpp)沟通。
这本书算是入门供应链产品经理最平滑的学习方式之一,非常值得一冲。



经常会有一些读者朋友在电子书群或者是星球群提问:“海外仓或者国内电商仓WMS的库存表要设计几张才能满足业务需求?”
这个问题,我在《跨境供应链:海外仓OTWB项目实战》相关的章节中有做过介绍,从产品设计的角度进行拆解,在WMS中,常见的库存维度有:
SKU库存,即仓库中的某个SKU一共有多少库存; 库位库存,即某个库位上一共有多个SKU,分别的库存有多少,也可以称之为“产品-库位库存”; 批次库存,即某个SKU一共有多少批次,分别每个批次的库存有多少,也可以称之为“产品-批次库存”; 库位-批次库存,是最细粒度的库存,即某个库位上存放了哪些SKU,这些SKU的批次分别有多少库存,也可以称之为“库位-批次库存”;

但是对于一些做技术的研发或者是关注技术的产品经理而言,他们会有更进一步的疑问和思考,那就是:从技术的角度出发,要设计几张表才能满足以上的库存查询维度,满足业务的需求。
本篇文章,我会结合我过往的实战项目经验和Gemini 2.5 Pro超强实力,来为大家拆解一下这个令不少人头痛的技术问题应该怎么处理会更好。探讨一种既能满足仓库对库存信息多维度、多视角查询的需求,又能支撑起复杂多变的业务流程的库存模块设计思路。
一、什么是“双层库存模型”?
你可能会想,既然“库位—批次库存”是最细粒度的,那我直接用一张表记录所有这些细节点不就行了吗?当我想知道某个SKU的总库存时,把这张表里对应SKU的记录加起来就好了。
理论上是这样没错。但实际操作中,尤其是对于库存量大、SKU种类多、出入库频繁的仓库来说,这种“单一细粒度库存模型”可能会遇到一些挑战:
SKU级别查询效率问题: 想象一下,如果一个SKU分布在几百上千个不同的库位和批次上,每次查询这个SKU的总可用量,系统都需要去扫描和聚合这成百上千条细粒度记录。当大量订单同时涌入,系统需要频繁进行这种查询时,性能压力就会非常大,可能导致系统响应缓慢,影响订单处理效率。 分阶段预占/锁定的表达不清晰: 很多WMS在处理订单时,会采用“先SKU级别预占/锁定,再库位批次级别分配”的两阶段模式,也就是电子书中提到的“先波后分”的玩法。如果只有一张细粒度的库存表,很难清晰、高效地表达和管理这种“SKU级别的意向性预占/锁定”。不过也有一些WMS为了偷懒,会在订单刚进来的时候就去预占/锁定具体的库位-批次库存,这种就是我们说的“先分后波”的逻辑。这两种玩法的优劣势,在电子书和星球中都已经讲过了,感兴趣的朋友自己去搜索关键词查看即可。
为了解决上面提到的2个问题,很多成熟的WMS会采用一种“双层库存模型”。顾名思义,就是用两层(或者说两种不同粒度的)数据表来共同管理库存信息。
第一层:SKU维度库存表(SKUInventorySummary)
这张表可以理解为一个“SKU库存的仪表盘”或者“宏观账本”。它不关心具体的库位和批次细节,只从SKU的整体层面,快速告诉你这个SKU在整个仓库(或者某个逻辑区域,比如某个货主的专属库存池)的宏观库存状态。
它的核心价值在于支持订单接入时的快速判断库存是否足够可用。当大量订单涌入系统时,WMS可以先快速查询这张表,判断某个SKU是否有足够的“总可用量”来满足订单需求,而不需要马上去遍历所有细粒度的物理库存记录。这样可以大大提升订单处理的并发能力和响应速度。

第二层:SKU-库位-批次维度库存表(LocationBatchInventory)
这张表就是我们前面提到的“最细粒度的库存账本”。它精确地记录了每一份物理库存(具体到某个SKU的某个批次)实际存放在哪个库位,有多少数量,以及它当前是否被某个具体的仓库作业分配了,或者是否因为其他原因被物理锁定了。
它的核心价值在于保证所有库内作业(上架、拣货、移库、盘点)的准确性。仓库的实际操作,比如让拣货员去某个货位拿多少个某个批次的货,都必须基于这张表里的精确信息。它也是实现库存完全可追溯的基础。

两层库存数据的协同方式
你可能会问,有了两张表,数据会不会乱?它们之间是怎么配合的呢?
其实可以这么理解:LocationBatchInventory
是基础,记录的是实实在在的物理库存。而 SKUInventorySummary
更像是一个动态的“汇总统计层”和“业务状态管理层”。
当发生实际的物理库存变动时(比如入库上架了一个新的批次,或者拣货出库了一批货), LocationBatchInventory
会首先被更新。然后,这些变动会汇总反映到SKUInventorySummary
的实际库存、可用库存等字段上。当发生业务状态的变更时(比如一个新订单进来,需要预占/锁定库存),会先在 SKUInventorySummary
上更新锁定库存的数量。当这个订单后续被分配到具体的库位和批次时,同时LocationBatchInventory
中对应库位批次的锁定库存数量会增加。
这种设计,关键在于如何确保这两层数据之间的同步和一致性。这通常是系统设计时需要重点考虑的地方,我们后面会再提到。
二、“双层库存模型”下的业务拆解
理解了双层库存模型的基本结构后,我们来看看在实际的仓库业务流程中,这两层库存数据是如何交互和变化的。
2.1 入库及上架流程
入库流程相对简单一些,但同样涉及到两层库存数据的更新。
收货与暂存
货物到仓,清点验收完成后,可能不会马上就能上架到具体的存储位,所以需要先放在一个“收货暂存库位”或者是“收货容器”中,可以把这部分的库存定义为“收货暂存库存”。
WMS处理:
如果想在系统中体现这部分“已到货但未上架”的库存,可以在 LocationBatchInventory
表中使用一个特殊的“虚拟库位”(比如叫“RCV_AREA”),记录这批货的SKU、批次和库存数量。此时,对应的 SKUInventorySummary
表中也会因为这些在暂存区的库存而增加,对应的实物库存和可用库存字段都会增加库存。这种方式的好处是,即使货还没上架,系统里已经能看到这批库存的存在了,对于库存可见性有帮助。
上架确认
仓库操作员将“收货暂存区”或者是“收货容器”中的货物,搬运到指定的存储库位,并确认上架。
WMS操作:
操作员在系统中(或通过PDA)确认某个SKU的某个批次,在哪个库位上架了多少数量。 WMS会在 LocationBatchInventory
表中创建一条新的记录,包含SKU、上架库位、批次以及上架数量。同时,之前在虚拟库位中的存放的记录也不会删除,只是会将库存数量置为0。表达的意思是从虚拟库位转移到了真实的物理库位中,所以虚拟库位的库存为0,而真实的库位则会增加库存。由于在一开始收货的时候 SKUInventorySummary
表中对应SKU的实物库存和可用库存已经增加过了,本次上架完成,并不会影响SKU维度库存的增加,所以就不需要再操作这张表的数据了。

2.2 订单处理流程
订单处理是WMS的核心流程之一,也是双层库存模型发挥重要作用的地方。
订单接收与SKU维度的锁定
比如你的电商平台(OMS系统)收到了一个客户订单,包含了几个不同的商品(SKU)和对应的数量。这个订单信息会推送到WMS。
WMS操作:
WMS首先会去查 SKUInventorySummary
表,看看订单中每个SKU的可用库存是否足够。如果都足够,WMS就会在 SKUInventorySummary
表中,为每个SKU增加相应的锁定数量。这个动作,可以理解为WMS对这批货打上了一个“预占/锁定”的标签。此时,我们并不关心这个SKU具体要从哪个货架、哪个批次出,只是在总量上先把它们“占住/锁定”。

这样做的好处是响应速度快。因为只操作
SKUInventorySummary
这张汇总表,计算和更新都比较轻量,能够快速告知OMS订单是否可以被接受,提升了订单处理的并发能力。
WMS分波与库位库存的分配
仓库运营人员可能会将一批“等待分配”的订单(在 SKUInventorySummary
中已经锁定库存)汇总并创建一个“波次”(Wave),然后系统会为这个波次里的所有订单SKU分配具体的库位-批次库存。
WMS操作:
WMS会先统计出波次中所有需要分配的SKU和数量。 然后,WMS会根据预设的分配策略(比如先进先出FIFO、临期先出FEFO、按客户指定批次、或者考虑库位远近优化拣货路径等),去 LocationBatchInventory
表中查找符合条件的、实际可用的库位-批次库存。一旦找到了合适的库位和批次,WMS就会在 LocationBatchInventory
表中,为这些被推荐的记录增加相应的锁定数量。

这一步完成了从“意向”到“实体”的转化。通过分配策略,可以确保出库的合理性(比如保证效期最新鲜),并且为后续的拣货作业生成了明确的指令(去哪个库位拿哪个批次的货)。
拣货下架流程
拣货员拿着PDA(或纸质拣货单),根据系统生成的拣货任务(基于上一步的分配结果),去指定的库位、批次拣取商品。
WMS操作:
当拣货员确认从某个库位、某个批次拣取了指定数量的商品后,WMS会更新 LocationBatchInventory
表:
减少对应记录的“锁定库存”,因为之前分配的货现在被拿走了 同时,也要减少对应记录的“实际数量”,因为实物库存实实在在地减少了,从货架上拿下来了
如果没有引入“拣货暂存库位”或者“拣货容器库位”的概念,那么此时的库存就是属于一个无法追溯的真空期,因为在库位-批次库存表中这部分的库存被扣减掉了,实物是转移到了拣货的容器中。
所以,为了规避出现这种明显的、已知的缺陷,建议在设计WMS库存体系的时候,要尽早地引入“拣货暂存库位”或者“拣货容器库位”的概念。当从库位上拣货下架之后,库存就会转移到拣货容器中,在系统中是可以记录这部分的数据,把容器当做一个虚拟库位,可以直接继承原拣货库位的商品的批次属性和数量等。
出库复核与发运
拣回来的商品经过复核(核对SKU、数量、批次等),打包,然后交给物流公司发运。
WMS操作:
当WMS确认这批货物已经实际离开仓库(比如物流交接扫描完成)后,需要进行最终的库存核销扣减。如果没有引入“拣货暂存库位”的玩法,那么这个核销扣减主要体现在 SKUInventorySummary
表中。如果引入了“拣货暂存库位”的玩法,那么这个核销扣减就要同时体现在SKUInventorySummary
和LocationBatchInventory
这两个表中。
这两个表都需要减少对应记录的“锁定库存”,因为之前预占/分配的货现在已经出库了 同时,也要减少对应记录的“实际库存”,因为实物库存实实在在地减少了,已经从仓库中发走了
当最细粒度的实物库存(
LocationBatchInventory
)减少后,汇总的实物库存(SKUInventorySummary
)自然也要跟着减少。而且这两张表的扣减需要有事务性,以确保数据是一致的。
2.3 库内管理流程:库存调整与移库
除了正常的出入库,仓库内部还会有很多管理性的操作,这些操作同样会影响库存数据,也需要考虑双层库存模型是如何变化的。
库存调整(盘盈亏、状态变更)
比如盘点时发现某个SKU多了(盘盈)或少了(盘亏),或者某个批次的商品因为过期需要从“良品”状态调整为“过期”状态等。
WMS操作:
对于数量调整(盘盈亏):直接修改 LocationBatchInventory
中对应SKU、库位、批次的库存数量。这个修改会通过汇总逻辑自动同步到SKUInventorySummary
的库存数量中。
库内移位
比如为了整理仓库库存,或者将某个商品从存储区移动到拣货区,需要将货物从一个库位移动到另一个库位。
WMS操作:
这个操作主要影响 LocationBatchInventory
表。源库位对应记录的实际库存减少。 目标库位对应记录的实际库存增加(如果是新的SKU/批次组合,则新增一条记录)。 对于 SKUInventorySummary
来说, 如果移库只是在同一个仓库内部,且不改变SKU的总物理数量或业务状态(比如没有从锁定状态移到可用状态),那么SKUInventorySummary
中的数据等不需要变化。
无论是库存调整、还是移库,仓库中所有的库存调整都必须有据可查,所以需要将这些痕迹给留存下来,也就是我们常说的“库存流水”。当仓库的库存发生变化,无论是增加、扣减、还是锁定、释放等,都应该写入到“库存流水表”中,便于后续的业务追溯和定位追查。
三、库存流水(InventoryLedger)要如何设计
前面我们聊了库存的“静态”模型(两层库存表),但库存是“活”的,它时刻都在发生变化。那么,如何记录这些变化,做到每一笔库存的增减都有迹可循呢?这就需要一个强大的“账房先生”——库存流水表 (InventoryLedger
)。
如果说两层库存表是某个时间点的“库存快照”,那么库存流水就是记录这些快照如何演变的“历史录像带”。
前面我们讨论了大多数WMS都会采用双层库存模型的玩法,此时你可能会想,那是不是也要设计两套库存流水表,一套对应 SKUInventorySummary
,一套对应 LocationBatchInventory
呢?