Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

cập nhật và chèn các truy vấn tạo ra một bế tắc

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để chỉnh sửa các giá trị của một INSERT trong một trình kích hoạt trên SQL Server?

  2. Tại sao các hàm có giá trị vô hướng của SQL Server hoạt động chậm hơn?

  3. SQL Server không hiển thị trong Visual Studio

  4. làm thế nào để buộc cài đặt phòng thu quản lý?

  5. Tại sao tham gia bên trái t-sql của tôi không hoạt động?