Imagine que tiene la siguiente estructura de tabla:
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
y ToPositionId
son posiciones de stock. Algunas ID de posición tienen un significado especial, por ejemplo 0
. Un evento desde o hacia 0
significa que el stock fue creado o eliminado. De 0
podría haber stock de una entrega y 0
podría ser un pedido enviado.
Actualmente, esta tabla contiene alrededor de 5,5 millones de filas. Calculamos el valor de stock para cada producto y lo posicionamos en una tabla de caché en un horario usando una consulta que se ve así:
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
Aunque esto se completa en un período de tiempo razonable (alrededor de 20 segundos), creo que esta es una forma bastante ineficiente de calcular los valores de las acciones. Raramente hacemos algo más que INSERT
: s en esta tabla, pero a veces entramos y ajustamos la cantidad o eliminamos una fila manualmente debido a errores de las personas que generan estas filas.
Tuve una idea de crear "puntos de control" en una tabla separada, calcular el valor hasta un punto específico en el tiempo y usarlo como valor inicial al crear nuestra tabla de caché de cantidad de stock:
ProductId | PositionId | Date | Quantity
-------------------------------------------------------
123 | 10002 | 2018-01-07 21:08:56 | 2
El hecho de que a veces cambiemos filas plantea un problema para esto, en ese caso también debemos recordar eliminar cualquier punto de control creado después de la fila de registro que cambiamos. Esto podría resolverse no calculando los puntos de control hasta ahora, pero deja un mes entre ahora y el último punto de control (muy raramente hacemos cambios tan atrás).
Es difícil evitar el hecho de que a veces necesitamos cambiar las filas y me gustaría poder hacerlo aún, no se muestra en esta estructura, pero los eventos de registro a veces están vinculados a otros registros en otras tablas, y agregando otra fila de registro a veces no es posible obtener la cantidad correcta.
La tabla de registro está, como puede imaginar, creciendo bastante rápido y el tiempo para calcular solo aumentará con el tiempo.
Entonces, a mi pregunta, ¿cómo resolverías esto? ¿Existe una forma más eficiente de calcular el valor actual de las acciones? ¿Es buena mi idea de los puntos de control?
Estamos ejecutando SQL Server 2014 Web (12.0.5511)
Plan de ejecución: https://www.brentozar.com/pastetheplan/?id=Bk8gyc68Q
De hecho, di el tiempo de ejecución incorrecto anterior, 20 años fue el tiempo que tomó la actualización completa de la caché. Esta consulta tarda entre 6 y 10 segundos en ejecutarse (8 segundos cuando creé este plan de consulta). También hay una combinación en esta consulta que no estaba en la pregunta original.