Các tùy chọn khóa của tôi cho một câu lệnh Hợp nhất là gì?


12

Tôi có một thủ tục lưu trữ thực hiện một MERGEtuyên bố .

Có vẻ như nó khóa toàn bộ bảng theo mặc định khi thực hiện hợp nhất.

Tôi đang gọi thủ tục được lưu trữ này bên trong một giao dịch nơi tôi cũng đang thực hiện một số nội dung khác và tôi ước nó chỉ khóa các hàng bị ảnh hưởng.

Tôi đã thử gợi ý MERGE INTO myTable WITH (READPAST)và nó dường như khóa ít hơn. Nhưng có một cảnh báo trong tài liệu ms nói rằng nó có thể chèn các khóa trùng lặp, bỏ qua ngay cả khóa chính.

Đây là lược đồ bảng của tôi:

CREATE TABLE StudentDetails
(
StudentID INTEGER PRIMARY KEY,
StudentName VARCHAR(15)
)
GO
INSERT INTO StudentDetails
VALUES(1,'WANG')
INSERT INTO StudentDetails
VALUES(2,'JOHNSON')
GO

CREATE TABLE StudentTotalMarks
(
Id INT IDENTITY PRIMARY KEY,
StudentID INTEGER REFERENCES StudentDetails,
StudentMarks INTEGER
)
GO
INSERT INTO StudentTotalMarks
VALUES(1,230)
INSERT INTO StudentTotalMarks
VALUES(2,255)
GO

Đây là thủ tục lưu trữ của tôi:

CREATE PROCEDURE MergeTest 
    @StudentId int,
    @Mark int
AS  

WITH Params
AS
(
    SELECT @StudentId as StudentId,
        @Mark as Mark
)
    MERGE StudentTotalMarks AS stm
    USING Params p
    ON stm.StudentID = p.StudentId
    WHEN MATCHED AND stm.StudentMarks > 250 THEN DELETE
    WHEN MATCHED THEN UPDATE SET stm.StudentMarks = p.Mark
    WHEN NOT MATCHED THEN
        INSERT(StudentID,StudentMarks)
        VALUES(p.StudentId, p.Mark);
GO

Đây là cách tôi quan sát khóa:

begin tran
EXEC MergeTest 1, 1

Và sau đó trong một phiên khác:

EXEC MergeTest 2, 2

Phiên thứ hai chờ đợi lần đầu tiên hoàn thành trước khi tiếp tục.


1
WITH (READPAST)hướng dẫn SQL Server bỏ qua các hàng bị khóa bởi các phiên khác. Bạn có chắc chắn muốn làm điều đó? Ngoài ra, có bao nhiêu hàng trong bảng này bạn đang sửa đổi? Chỉ cho chúng tôi lược đồ bảng (bao gồm các chỉ mục) và MERGEcâu lệnh bạn đang chạy.
Nick Chammas

@NickChammas cảm ơn bạn đã giúp đỡ, tôi đã cập nhật câu hỏi với các chi tiết. Tôi tưởng tượng READPAST sẽ rất tệ ...
John Buchanan

Câu trả lời:


11

Bạn cần cung cấp cho bộ xử lý truy vấn một đường dẫn truy cập hiệu quả hơn để xác định vị trí StudentTotalMarkscác bản ghi. Như được viết, truy vấn yêu cầu quét toàn bộ bảng với một vị từ còn lại [StudentID] = [@StudentId]được áp dụng cho mỗi hàng:

Kế hoạch quét

Công cụ sẽ Ukhóa (cập nhật) khi đọc như một cách phòng thủ cơ bản chống lại nguyên nhân phổ biến của các bế tắc chuyển đổi. Hành vi này có nghĩa là các khối thực thi thứ hai khi cố lấy Ukhóa trên hàng đã bị khóa bằng khóa X(độc quyền) bởi lần thực hiện đầu tiên.

Chỉ mục sau đây cung cấp đường dẫn truy cập tốt hơn, tránh lấy các Ukhóa không cần thiết :

CREATE UNIQUE INDEX uq1 
ON dbo.StudentTotalMarks (StudentID) 
INCLUDE (StudentMarks);

Kế hoạch truy vấn hiện bao gồm thao tác tìm kiếm trên StudentID = [@StudentId], vì vậy các Ukhóa chỉ được yêu cầu trên các hàng đích:

Kế hoạch tìm kiếm

Chỉ mục không bắt buộc phải UNIQUEgiải quyết vấn đề trong tay (mặc dù điều INCLUDEnày là bắt buộc để biến nó thành chỉ số bao trùm cho truy vấn này).

Làm StudentIDviệc PRIMARY KEYcủa StudentTotalMarksbảng cũng sẽ giải quyết vấn đề con đường truy cập (và dường như dư thừa Idcột có thể được gỡ bỏ). Bạn phải luôn luôn thực thi các khóa thay thế bằng một UNIQUEhoặc PRIMARY KEYràng buộc (và tránh thêm các khóa thay thế vô nghĩa mà không có lý do chính đáng).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.