Tôi có một vấn đề với một lượng lớn INSERT đang chặn các hoạt động CHỌN của tôi.
Lược đồ
Tôi có một cái bàn như thế này:
CREATE TABLE [InverterData](
[InverterID] [bigint] NOT NULL,
[TimeStamp] [datetime] NOT NULL,
[ValueA] [decimal](18, 2) NULL,
[ValueB] [decimal](18, 2) NULL
CONSTRAINT [PrimaryKey_e149e28f-5754-4229-be01-65fafeebce16] PRIMARY KEY CLUSTERED
(
[TimeStamp] DESC,
[InverterID] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF
, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON)
)
Tôi cũng có quy trình trợ giúp nhỏ này, cho phép tôi chèn hoặc cập nhật (cập nhật về xung đột) bằng lệnh MERGE:
CREATE PROCEDURE [InsertOrUpdateInverterData]
@InverterID bigint, @TimeStamp datetime
, @ValueA decimal(18,2), @ValueB decimal(18,2)
AS
BEGIN
MERGE [InverterData] AS TARGET
USING (VALUES (@InverterID, @TimeStamp, @ValueA, @ValueB))
AS SOURCE ([InverterID], [TimeStamp], [ValueA], [ValueB])
ON TARGET.[InverterID] = @InverterID AND TARGET.[TimeStamp] = @TimeStamp
WHEN MATCHED THEN
UPDATE
SET [ValueA] = SOURCE.[ValueA], [ValueB] = SOURCE.[ValueB]
WHEN NOT MATCHED THEN
INSERT ([InverterID], [TimeStamp], [ValueA], [ValueB])
VALUES (SOURCE.[InverterID], SOURCE.[TimeStamp], SOURCE.[ValueA], SOURCE.[ValueB]);
END
Sử dụng
Bây giờ tôi đã chạy các phiên bản dịch vụ trên nhiều máy chủ thực hiện cập nhật lớn bằng cách gọi [InsertOrUpdateInverterData]
thủ tục nhanh chóng.
Ngoài ra còn có một trang web thực hiện các truy vấn CHỌN trên [InverterData]
bảng.
Vấn đề
Nếu tôi thực hiện các truy vấn CHỌN trên [InverterData]
bảng thì chúng được tiến hành trong các khoảng thời gian khác nhau, phụ thuộc vào việc sử dụng INSERT của các phiên bản dịch vụ của tôi. Nếu tôi tạm dừng tất cả các phiên bản dịch vụ thì CHỌN nhanh như chớp, nếu cá thể đó thực hiện thao tác chèn nhanh thì các CHỌN sẽ rất chậm hoặc thậm chí là hết thời gian chờ.
Nỗ lực
Tôi đã thực hiện một số CHỌN trên [sys.dm_tran_locks]
bàn để tìm các quy trình khóa, như thế này
SELECT
tl.request_session_id,
wt.blocking_session_id,
OBJECT_NAME(p.OBJECT_ID) BlockedObjectName,
h1.TEXT AS RequestingText,
h2.TEXT AS BlockingText,
tl.request_mode
FROM sys.dm_tran_locks AS tl
INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address
INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id
INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id
INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id
CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2
Đây là kết quả:
S = Chia sẻ. Phiên tổ chức được cấp quyền truy cập chung vào tài nguyên.
Câu hỏi
Tại sao các CHỌN bị chặn bởi [InsertOrUpdateInverterData]
thủ tục chỉ sử dụng các lệnh MERGE?
Tôi có phải sử dụng một số loại giao dịch với chế độ cách ly được xác định bên trong [InsertOrUpdateInverterData]
không?
Cập nhật 1 (liên quan đến câu hỏi từ @Paul)
Dựa trên báo cáo nội bộ của máy chủ MS-SQL về [InsertOrUpdateInverterData]
thống kê sau:
- Thời gian CPU trung bình: 0,12ms
- Quá trình đọc trung bình: 5,76 mỗi / s
- Quá trình ghi trung bình: 0,4 mỗi / s
Dựa vào điều này, có vẻ như lệnh MERGE hầu như bận rộn với các hoạt động đọc sẽ khóa bảng! (?)
Cập nhật 2 (liên quan đến câu hỏi từ @Paul)
Các [InverterData]
bảng như đã sau số liệu thống kê lưu trữ:
- Dung lượng dữ liệu: 26.901,86 MB
- Số hàng: 131.827.749
- Phân vùng: đúng
- Số lượng phân vùng: 62
Dưới đây là tập kết quả sp_WhoIsActive hoàn chỉnh (nhất) :
SELECT
chỉ huy
- dd hh: mm: ss.mss: 00 00: 01: 01.930
- phiên_id: 73
- Wait_info: (12629ms) LCK_M_S
- CPU: 198
- chặn_session_id: 146
- đọc: 99.368
- viết: 0
- tình trạng: bị đình chỉ
- open_tran_count: 0
[InsertOrUpdateInverterData]
Lệnh chặn
- dd hh: mm: ss.mss: 00 00: 00: 00.330
- phiên_id: 146
- chờ đợi
- CPU: 3.972
- chặn_session_id: NULL
- đọc: 376,95
- viết: 126
- tình trạng: đang ngủ
- open_tran_count: 1
([TimeStamp] DESC, [InverterID] ASC)
ngoại hình giống như một sự lựa chọn kỳ lạ đối với nhóm chỉ số. Tôi có nghĩa làDESC
một phần.