库存数据库设计[关闭]
Posted
技术标签:
【中文标题】库存数据库设计[关闭]【英文标题】:Inventory database design [closed] 【发布时间】:2010-09-22 04:10:03 【问题描述】:这不是一个真正关于“编程”的问题(不特定于任何语言或数据库),而是更多关于设计和架构的问题。这也是“什么是做 X 的最佳方式”类型的问题。我希望不会引起太多“宗教”争议。
在过去,我开发的系统以某种方式保留某种形式的物品库存(与什么物品无关)。一些使用不支持事务的语言/数据库。在这些情况下,我选择不在项目记录的字段中保存项目手头数量。取而代之的是,现有数量是计算收到的总库存 - 已售库存的总和。由于软件,这导致库存几乎没有差异。这些表已正确索引并且性能良好。有一个存档过程,以防记录数量开始影响性能。
现在,几年前我开始在这家公司工作,我继承了一个跟踪库存的系统。但是数量保存在一个字段中。注册条目后,收到的数量将添加到项目的数量字段中。当一件商品售出时,数量会被减去。这导致了分歧。在我看来这不是正确的方法,但这里的以前的程序员发誓。
我想知道对于设计此类系统的正确方法是否存在共识。还有哪些可用资源(印刷版或在线版)可用于寻求这方面的指导。
谢谢
【问题讨论】:
当你说“以前的程序员在这里发誓”时,你的意思是他们每次必须工作时都发誓吗? 【参考方案1】:我在目前的公司看到了这两种方法,并且肯定会倾向于第一种(根据股票交易计算总数)。
如果您只在某处的某个字段中存储一个总量,那么您不知道您是如何得出该数字的。没有交易历史记录,您最终可能会遇到问题。
我编写的最后一个系统通过将每笔交易存储为具有正数或负数的记录来跟踪库存。我发现它效果很好。
【讨论】:
+1 我也有同样的困境,现在我认为这是最好的选择 @Neil - 你能评论一下这种方法的性能吗?这似乎是最受欢迎的方法,但如果您有数百种产品和数千笔交易,您如何或何时计算累积总数。还是您只是将累积的总数存储在另一个地方,因为知道您可以在需要时重新计算? 我进行了一项测试 - 我发布了超过 2000 种产品的大约 300 万条记录(正负库存调整)。按 SKU 分组的所有行的总和只需要几分之一秒的时间。我不得不说我对它的运行速度感到非常震惊,而且对于我正在做的项目,我肯定还有数量级的增长,并且不需要很快担心它。显然,如果您在网站上显示实时库存总数,您可能希望缓存它们,但即使是所有 2000 种产品,我也几乎可以立即计算出总和。 银行/会计系统对交易(借方或贷方)执行类似的操作,通常作为单独的字段但具有相同的总和效果。主要是出于运营原因,会创建每月余额(通常有一个验证月末流程),但这也是一种能够将 12 个每月增量数字相加的方法,以便快速相加一年而不是一年中的每笔交易.当跨年和数百万个帐户完成时,性能优势是真实的,并且还允许在几个月前进行更正,只需要重新计算当月的收盘价。 你应该同时应用,1个字段是数量,1个表用于交易。数量字段可以在需要时重新计算。你需要这个字段是因为性能。月底的时候。我们应该将所有数字从前一个月移到新月份。这是我的ERP系统工作。并且运作良好【参考方案2】: The Data Model Resource Book, Vol. 1: A Library of Universal Data Models for All Enterprises The Data Model Resource Book, Vol. 2: A Library of Data Models for Specific Industries The Data Model Resource Book: Universal Patterns for Data Modeling我有第 1 卷和第 2 卷,这些在过去很有帮助。
【讨论】:
In order to be immediately helpful to readers (and avoid link-rot), we prefer answers that provide at least a summary of the solution directly, with links used to offer additional information.【参考方案3】:视情况而定,库存系统不仅仅是对物品进行计数。例如,出于会计目的,您可能需要了解基于 FIFO(先进先出)模型的库存会计价值。这不能通过简单的“收到的总库存 - 售出的总库存”公式来计算。但是他们的模型可能会很容易地计算出这一点,因为他们会随时修改会计价值。我不想详细说明,因为这不是编程问题,但如果他们发誓,也许你没有完全理解他们必须满足的所有要求。
【讨论】:
【参考方案4】:两者都有效,具体取决于具体情况。当满足以下条件时,前者是最好的:
求和的项目数比较少 很少或根本不需要考虑特殊情况(退货、调整等) 库存项目数量并不经常需要另一方面,如果物品数量多,异常情况多,访问频繁,那么保持物品数量会更有效率
还请注意,如果您的系统存在差异,则它存在错误,应追踪并消除这些错误
我已经做过两种方式的系统,两种方式都可以正常工作 - 只要你不忽略错误!
【讨论】:
嗯。回报是不是真的很特别?除非您销售的是纯粹易腐烂的物品或其他无法转售的物品 @Simon:我编写的早期库存系统之一是用于定制冰淇淋店。回报不仅异常,而且几乎是不可能的;-)【参考方案5】:考虑现有系统以及更改它的成本和风险非常重要。我使用的数据库存储类似于您的库存,但它包括审计周期和存储调整,就像收据一样。它似乎运作良好,但参与的每个人都训练有素,而且仓库工作人员学习新程序的速度并不快。
在您的情况下,如果您希望在不更改整个数据库结构的情况下进行更多跟踪,那么我建议您添加一个跟踪表(类似于您的“交易”解决方案),然后将更改记录到库存等级。将大多数更改更新到库存级别应该不会太难,以便它们也留下交易记录。您还可以添加一个定期任务以每隔几个小时左右将库存级别备份到事务表中,这样即使您错过了一个事务,您也可以发现更改发生的时间或回滚到之前的状态。
如果您想了解大型应用程序是如何处理的,请查看 SugarCRM,他们有库存管理模块,但我不确定它如何存储数据。
【讨论】:
【参考方案6】:我认为这实际上是一个一般性的最佳实践问题,即每次需要总数时进行(相对)昂贵的计数,而不是每次发生变化时进行计数,然后将计数存储在字段中并随时读取该字段你需要一个总数。
如果我不能使用事务,我会在每次需要总数时使用实时计数。如果交易可用,则可以安全地执行库存更新操作并在同一交易中保存重新盘点的总数,这将确保计数的准确性(尽管我不确定这是否适用于多个用户访问数据库)。
但是,如果性能不是一个真正的大问题(并且现代数据库在计算行数方面已经足够好,我什至很少会担心这一点)我会坚持每次都使用实时计数。
【讨论】:
【参考方案7】:我会选择第一种方式,在哪里
计算手头数量 收到的总库存 - 总计 已售出的库存
正确的方式,IMO。
编辑:我还想考虑系统中的任何库存损失/损坏,但我相信你已经涵盖了。
【讨论】:
【参考方案8】:我以前曾研究过解决此问题的系统。我认为理想的解决方案是预先计算的列,它可以让您两全其美。您的总数将是某处的一个字段,因此无需昂贵的查找,但它不能与您的其余数据不同步(数据库保持完整性)。我不记得哪些 RDMS 支持预先计算的列,但如果您没有事务,那可能也不可用。
您可能会使用触发器伪造预先计算的列(非常有效......我认为没有缺点)。不过,您可能需要交易。恕我直言,在进行这种受控的非规范化时保持数据完整性是触发器的唯一合法用途。
【讨论】:
【参考方案9】:Django-inventory 更适合固定资产,但可能会给你一些想法。
IE:ItemTemplate(类)-> ItemsOnHand(实例)
ItemsOnHand 可以链接到更多的 ItemTemplates;示例打印机和墨盒是必需的。这也允许为每个 ItemOnHand 设置重新订购点。
每个 ItemsOnHand 都链接到 InventoryTransactions,这样便于审核。 为了避免从数千个库存交易中计算实际的现有项目,使用了只是余额 + 日期的检查点。计算手头上的项目以查找最近的检查点并开始添加或减去项目以查找当前的项目余额。定期定义新的检查点。
【讨论】:
【参考方案10】:我可以看到拥有两列的一些好处,但我没有关注关于差异的部分 - 您似乎暗示拥有两列(进出)比单列更不容易出现差异(当前的)。这是为什么呢?
【讨论】:
【参考方案11】:没有一列或两列,我的意思是“收到的总库存 - 售出的总库存”是这样的:
Select sum(quantity) as inventory_received from Inventory_entry
Select sum(quantity) as inventory_sold from Sales_items
然后
Qunatity_on_hand = inventory_received - inventory_sold
请记住,我对此和最初的解释过于简单化了。我知道库存还有更多只是跟踪数量,但在这种情况下,这就是问题所在,也是我们想要解决的问题。此时改变它的原因恰恰是支持当前设计引起的问题的成本。
我还想提一下,虽然这不是“编码”问题,但与算法和设计有关,恕我直言,这是非常重要的主题。
到目前为止,感谢大家的回答。
纳尔逊马尔莫
【讨论】:
这种特殊解决方案的缺点是性能会随着时间的推移而变得越来越差,因为您必须无限期地记录所有收到或出售的库存,以便获得正确的当前数量!【参考方案12】:我们解决不同的问题,但我们处理其中一些问题的方法可能会让您感兴趣。
我们允许系统做出“最佳猜测”,并定期向用户提供关于任何看起来错误的猜测的反馈。
要将其应用于库存,您可以有 3 个字段:
inventory_received
inventory_sold
estimated_on_hand
然后,您可以按照以下方式运行一个流程(每天?):
SELECT *
FROM Inventory
WHERE estimated_on_hand != inventory_received - inventory_sold
当然,这取决于用户查看此警报并对其采取措施。
此外,您可以通过更新inventory_sold/received 或添加另一个字段“inventory_adjustment”来以某种方式重置库存,该字段可能是正数或负数。
...只是一些想法。希望它有帮助。
【讨论】:
以上是关于库存数据库设计[关闭]的主要内容,如果未能解决你的问题,请参考以下文章