Vyhněte se kurzorům, tento dotaz je nepotřeboval. SQL není imperativní jazyk (to je důvod, proč má špatné jméno, protože jej všichni používají jako jeden ) - je to nastavený jazyk.
První věc, kterou můžete udělat, je urychlit základní provádění vašeho SQL, méně času na analýzu/provádění dotazu znamená menší pravděpodobnost uváznutí:
- Všem tabulkám předponujte
[dbo]
– to sníží až 30 % z fáze analýzy. - Alias vašich tabulek – odřízne to malé množství z fáze plánování.
- Uvádění identifikátorů může věci urychlit.
- Toto jsou tipy od bývalého SQL-PM, než se to někdo rozhodne zpochybnit.
K aktualizaci dat můžete použít CTE a poté použít UPDATE ... FROM ... SELECT
prohlášení k provedení skutečných aktualizací. Bude to rychlejší než kurzor, protože kurzory jsou pomalé ve srovnání s operacemi čistého setu (dokonce i ten nejrychlejší kurzor „požární hadice“, jako je ten váš). Méně času stráveného aktualizací znamená menší šanci na zablokování. Poznámka:Nemám vaše původní tabulky, nemohu to ověřit – zkontrolujte to s vývojovou DB.
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;
Kromě toho můžete zakázat uzamčení PAGE na vašem indexu, sníží se tím pravděpodobnost, že několik řádků uzamkne celou stránku (kvůli eskalaci zamykání je třeba zamknout pouze určité procento řádků, než bude celá stránka pouze uzamčena).
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
To jen zmírní šance na uváznutí. Můžete zkusit omezit @nyní datum v minulosti (tj. today - 1 day
), abyste se ujistili, že vložený řádek nespadá do predikátu aktualizace; je pravděpodobné, že zcela zabrání uváznutí.