sql >> Databáze >  >> RDS >> Sqlserver

aktualizovat a vkládat dotazy vytvářející uváznutí

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í.



  1. utf8_bin vs. utf_unicode_ci

  2. Jak monitorovat stav instancí databáze

  3. Vyberte, kde je počet jednoho pole větší než jedna

  4. MySQL:Proč 5. ID v klauzuli IN drasticky mění plán dotazů?