Hãy tưởng tượng rằng bạn có cấu trúc bảng sau:
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
và ToPositionId
các vị trí cổ phiếu. Một số vị trí ID: s có ý nghĩa đặc biệt, ví dụ 0
. Một sự kiện từ hoặc 0
có nghĩa là cổ phiếu đã được tạo hoặc xóa. Từ 0
có thể là chứng khoán từ một giao hàng và 0
có thể là một đơn đặt hàng được vận chuyển.
Bảng này hiện đang giữ khoảng 5,5 triệu hàng. Chúng tôi tính toán giá trị chứng khoán cho từng sản phẩm và vị trí vào bảng bộ đệm theo lịch biểu bằng cách sử dụng truy vấn trông giống như sau:
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
Mặc dù điều này hoàn thành trong một khoảng thời gian hợp lý (khoảng 20 giây), tôi cảm thấy như đây là một cách tính không hiệu quả để tính các giá trị chứng khoán. Chúng tôi hiếm khi làm bất cứ điều gì ngoại trừ INSERT
: trong bảng này, nhưng đôi khi chúng tôi đi vào và điều chỉnh số lượng hoặc xóa một hàng theo cách thủ công do những người tạo ra các hàng này.
Tôi đã có ý tưởng tạo "điểm kiểm tra" trong một bảng riêng biệt, tính toán giá trị đến một thời điểm cụ thể và sử dụng đó làm giá trị bắt đầu khi tạo bảng bộ đệm số lượng chứng khoán của chúng tôi:
ProductId | PositionId | Date | Quantity
-------------------------------------------------------
123 | 10002 | 2018-01-07 21:08:56 | 2
Thực tế là đôi khi chúng ta thay đổi các hàng đặt ra một vấn đề cho vấn đề này, trong trường hợp đó chúng ta cũng phải nhớ xóa bất kỳ điểm kiểm tra nào được tạo sau khi hàng nhật ký chúng ta thay đổi. Điều này có thể được giải quyết bằng cách không tính toán các điểm kiểm tra cho đến bây giờ, nhưng để lại một tháng từ giờ đến điểm kiểm tra cuối cùng (chúng tôi rất hiếm khi thực hiện các thay đổi lùi xa).
Thực tế là đôi khi chúng ta cần thay đổi các hàng là điều khó tránh và tôi muốn vẫn có thể làm điều này, nó không được hiển thị trong cấu trúc này nhưng các sự kiện nhật ký đôi khi được gắn với các bản ghi khác trong các bảng khác và thêm một hàng nhật ký khác để có được số lượng đúng đôi khi không thể.
Bảng nhật ký là, như bạn có thể tưởng tượng, phát triển khá nhanh và thời gian để tính toán sẽ chỉ tăng theo thời gian.
Vì vậy, với câu hỏi của tôi, làm thế nào bạn sẽ giải quyết điều này? Có cách nào hiệu quả hơn để tính giá trị cổ phiếu hiện tại? Là ý tưởng của tôi về trạm kiểm soát là một tốt?
Chúng tôi đang chạy SQL Server 2014 Web (12.0.5511)
Kế hoạch thực hiện: https://www.brentozar.com/pastetheplan/?id=Bk8gyc68Q
Tôi thực sự đã đưa ra thời gian thực hiện sai ở trên, 20s là thời gian mà bản cập nhật hoàn chỉnh của bộ đệm đã mất. Truy vấn này mất khoảng 6-10 giây để chạy (8 giây khi tôi tạo kế hoạch truy vấn này). Ngoài ra còn có một tham gia trong truy vấn này không có trong câu hỏi ban đầu.