Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

perbarui dan masukkan kueri yang membuat kebuntuan

Hindari kursor, kueri itu tidak membutuhkannya. SQL tidak bahasa imperatif (itulah sebabnya ia mendapat nama buruk karena semua orang menggunakannya sebagai satu ) - ini adalah bahasa yang ditetapkan.

Hal pertama yang dapat Anda lakukan adalah mempercepat eksekusi dasar SQL Anda, lebih sedikit waktu parsing/eksekusi kueri berarti lebih sedikit kemungkinan kebuntuan:

  • Awal semua tabel Anda dengan [dbo] - ini memotong hingga 30% dari tahap penguraian.
  • Alias ​​meja Anda - ini memotong sedikit dari tahap perencanaan.
  • Mengutip pengenal mungkin mempercepat segalanya.
  • Ini adalah tips dari mantan SQL-PM sebelum ada yang memutuskan untuk membantahnya.

Anda dapat menggunakan CTE untuk memperbarui data dan kemudian menggunakan UPDATE ... FROM ... SELECT pernyataan untuk melakukan pembaruan yang sebenarnya. Ini akan lebih cepat daripada kursor, karena kursor anjing lambat bila dibandingkan dengan operasi set bersih (bahkan kursor 'selang kebakaran' tercepat seperti milik Anda). Lebih sedikit waktu yang dihabiskan untuk memperbarui berarti lebih sedikit kemungkinan kebuntuan. Catatan:Saya tidak memiliki tabel asli Anda, saya tidak dapat memvalidasi ini - jadi periksa dengan DB pengembangan.

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;

Selain itu, Anda dapat melarang penguncian PAGE pada indeks Anda, ini akan mengurangi kemungkinan beberapa baris mengunci seluruh halaman (karena eskalasi penguncian, hanya persentase tertentu dari baris yang perlu dikunci sebelum seluruh halaman dikunci).

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

Ini hanya akan mengurangi kemungkinan kebuntuan. Anda dapat mencoba membatasi @sekarang tanggal di masa lalu (yaitu today - 1 day ) untuk memastikan bahwa baris yang disisipkan tidak termasuk dalam predikat pembaruan; kemungkinan itu akan mencegah kebuntuan sepenuhnya.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ubah tabel lalu perbarui dalam satu pernyataan

  2. IDENTITY() vs IDENTITY() di SQL Server:Apa Bedanya?

  3. Cara Mengembalikan Substring dari String di SQL Server menggunakan Fungsi SUBSTRING()

  4. VMware CPU Hot Plug vNUMA Effects pada SQL Server

  5. SSIS API:Bagaimana cara mengetahui Antarmuka untuk melemparkan __COMObject?