假设您具有以下表结构:
LogId | ProductId | FromPositionId | ToPositionId | Date | Quantity
-----------------------------------------------------------------------------------
1 | 123 | 0 | 10002 | 2018-01-01 08:10:22 | 5
2 | 123 | 0 | 10003 | 2018-01-03 15:15:10 | 9
3 | 123 | 10002 | 10004 | 2018-01-07 21:08:56 | 3
4 | 123 | 10004 | 0 | 2018-02-09 10:03:23 | 1
FromPositionId
并且ToPositionId
是库存头寸。某些职位ID:具有特殊含义,例如0
。来自或到的事件0
表示已创建或删除库存。从0
可能是交货的库存,到0
可能是发货的订单。
该表当前包含约550万行。我们使用类似于以下查询的查询来计算每种产品的库存价值并按计划将其排入缓存表中:
WITH t AS
(
SELECT ToPositionId AS PositionId, SUM(Quantity) AS Quantity, ProductId
FROM ProductPositionLog
GROUP BY ToPositionId, ProductId
UNION
SELECT FromPositionId AS PositionId, -SUM(Quantity) AS Quantity, ProductId
FROM ProductPositionLog
GROUP BY FromPositionId, ProductId
)
SELECT t.ProductId, t.PositionId, SUM(t.Quantity) AS Quantity
FROM t
WHERE NOT t.PositionId = 0
GROUP BY t.ProductId, t.PositionId
HAVING SUM(t.Quantity) > 0
即使完成了合理的时间(大约20秒),我仍然觉得这是计算股票价值的一种非常低效的方法。INSERT
在此表中,我们很少执行:s以外的任何操作,但有时由于生成这些行的人员的错误,我们会进入并调整数量或手动删除一行。
我有一个想法,在一个单独的表中创建“检查点”,计算直到特定时间点的值,并在创建我们的库存量缓存表时将其用作起始值:
ProductId | PositionId | Date | Quantity
-------------------------------------------------------
123 | 10002 | 2018-01-07 21:08:56 | 2
我们有时会更改行这一事实对此造成了问题,在这种情况下,我们还必须记住删除在更改日志行之后创建的所有检查点。可以通过不算到目前为止的检查点来解决,而要在现在到最后一个检查点之间留一个月的时间(我们很少会这么远地进行更改)。
我们有时需要更改行的事实很难避免,我仍然希望能够做到这一点,虽然这种结构未显示,但是日志事件有时与其他表中的其他记录相关联,并添加了另一个日志行有时无法获得正确的数量。
您可以想象,日志表增长很快,并且计算时间只会随着时间而增加。
所以对我的问题,您将如何解决呢?有没有更有效的方法来计算当前库存值?我对检查站的想法好吗?
我们正在运行SQL Server 2014 Web(12.0.5511)
执行计划:https : //www.brentozar.com/pastetheplan/?id=Bk8gyc68Q
实际上,我在上面给了错误的执行时间,这是完全更新缓存所花费的时间20秒。该查询大约需要6-10秒才能运行(我创建此查询计划时需要8秒)。此查询中还有一个联接不在原始问题中。