sql >> Database >  >> RDS >> Sqlserver

update en voeg query's in die een impasse creëren

Vermijd cursors, die zoekopdracht had ze niet nodig. SQL is niet een gebiedende wijs (daarom krijgt het een slechte naam omdat iedereen het als één taal gebruikt ) - het is een ingestelde taal.

Het eerste dat u kunt doen, is de basisuitvoering van uw SQL versnellen, minder tijd voor het parseren/uitvoeren van de query betekent minder kans op een impasse:

  • Voorvoegsel aan al uw tabellen [dbo] - dit scheelt tot 30% van de ontledingsfase.
  • Uw tafels alias - het scheelt een klein deel van de planningsfase.
  • Citeer-ID's kunnen dingen versnellen.
  • Dit zijn tips van een ex-SQL-PM voordat iemand besluit het te betwisten.

U kunt een CTE gebruiken om de gegevens bij te werken en vervolgens een UPDATE ... FROM ... SELECT gebruiken verklaring om de daadwerkelijke updates uit te voeren. Dit is sneller dan een cursor, omdat cursors hond traag zijn in vergelijking met schone set-operaties (zelfs de snelste 'brandslang'-cursor zoals die van jou). Minder tijd besteed aan het updaten betekent minder kans op een impasse. Opmerking:ik heb je originele tabellen niet, ik kan dit niet valideren - dus vergelijk het met een ontwikkelings-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;

Verder zou u PAGINA-vergrendelingen op uw index kunnen weigeren, dit verkleint de kans dat een paar rijen een hele pagina vergrendelen (vanwege de escalatie van de vergrendeling hoeft slechts een bepaald percentage rijen te worden vergrendeld voordat de hele pagina wordt vergrendeld).

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

Dit verkleint alleen de kans op een impasse. Je zou kunnen proberen @nu een datum in het verleden te beperken (d.w.z. today - 1 day ) om ervoor te zorgen dat de ingevoegde rij niet in het update-predikaat valt; de kans is groot dat het de impasse volledig zal voorkomen.



  1. jdbc4.MySQLSyntaxErrorException:Tabel bestaat niet in database

  2. SQL-query om datums tussen twee datums te selecteren

  3. De database [dbName] is niet toegankelijk. (Objectverkenner)

  4. Vreemd resultaat met UNION en ORDER BY