Tránh con trỏ, truy vấn đó không cần đến chúng. SQL thì không ngôn ngữ mệnh lệnh ( đó là lý do tại sao nó có tên xấu vì mọi người đều sử dụng nó như một ) - đó là một ngôn ngữ cố định.
Điều đầu tiên bạn có thể làm là tăng tốc độ thực thi cơ bản của SQL, ít thời gian hơn để phân tích cú pháp / thực thi truy vấn có nghĩa là ít nguy cơ xảy ra bế tắc hơn:
- Đặt tiền tố cho tất cả các bảng của bạn bằng
[dbo]
- điều này cắt giảm tới 30% giai đoạn phân tích cú pháp. - Đặt bí danh cho các bảng của bạn - nó cắt bớt một phần nhỏ giai đoạn lập kế hoạch.
- Trích dẫn số nhận dạng có thể tăng tốc mọi thứ.
- Đây là các mẹo từ một cựu SQL-PM trước khi bất kỳ ai quyết định tranh chấp nó.
Bạn có thể sử dụng CTE để cập nhật dữ liệu và sau đó sử dụng UPDATE ... FROM ... SELECT
tuyên bố để thực hiện các cập nhật thực tế. Thao tác này sẽ nhanh hơn con trỏ vì con trỏ chậm khi so sánh với các hoạt động thiết lập sạch (ngay cả con trỏ 'vòi chữa cháy' nhanh nhất như của bạn). Thời gian cập nhật ít hơn có nghĩa là ít có nguy cơ xảy ra bế tắc hơn. Lưu ý:Tôi không có các bảng ban đầu của bạn, tôi không thể xác thực điều này - vì vậy hãy kiểm tra nó với DB phát triển.
DECLARE @nowTime datetime = convert(datetime, @now, 21);
WITH [DailyAggregates] AS
(
SELECT
[D].[dailyId] AS [dailyId],
[D].[spentDaily] AS [spentDaily],
[D].[impressionsCountCache] AS [impressionsCountCache],
SUM([I].[amountCharged]) as [sumCharged],
COUNT([I].[impressionId]) as [countImpressions]
FROM [dbo].[Daily] AS [D]
INNER JOIN [dbo].[Impressions] AS [I]
ON [I].[dailyId] = [D].[dailyId]
WHERE [I].[isCharged] = 0
AND [I].[showTime] < @nowTime
AND [D].[isActive] = 1
GROUP BY [D].[dailyId], [D].[spentDaily], [D].[impressionsCountCache]
)
UPDATE [dbo].[Daily]
SET [spentDaily] = [A].[spentDaily] + [A].[sumCharged],
[impressionsCountCache] = [A].[impressonsCountCache] + [A].[countImpressions]
FROM [Daily] AS [D]
INNER JOIN [DailyAggregates] AS [A]
ON [D].[dailyId] = [A].[dailyId];
UPDATE [dbo].[Impressions]
SET [isCharged] = 1
WHERE [showTime] < @nowTime
AND [isCharged] = 0;
Hơn nữa, bạn có thể không cho phép khóa PAGE trên chỉ mục của mình, điều này sẽ làm giảm khả năng một vài hàng khóa toàn bộ trang (vì khóa leo thang, chỉ một tỷ lệ hàng nhất định cần được khóa trước khi toàn bộ trang bị khóa).
CREATE NONCLUSTERED INDEX [IDX_Impressions_isCharged_showTime] ON [dbo].[Impressions]
(
[showTime] ASC, -- I have a hunch that switching these around might have an effect.
[isCharged] ASC
)
WITH (ALLOW_PAGE_LOCKS = OFF)
ON [PRIMARY]
GO
Điều này sẽ chỉ giảm thiểu nguy cơ bế tắc. Bạn có thể thử giới hạn @now một ngày trong quá khứ (tức là today - 1 day
) để đảm bảo rằng hàng được chèn không rơi vào vị từ cập nhật; rất có thể nó sẽ ngăn chặn hoàn toàn sự bế tắc.