Đã thêm 7/11 Vấn đề là sự bế tắc xảy ra do quét chỉ mục trong MERGE THAM GIA. Trong trường hợp này, một giao dịch cố gắng lấy khóa S trên toàn bộ chỉ mục tại bảng cha FK, nhưng trước đó một giao dịch khác đặt khóa X trên một giá trị chính của chỉ mục.
Hãy để tôi bắt đầu với một ví dụ nhỏ (TSQL2012 DB từ 70-461 nguồn được sử dụng):
CREATE TABLE [Sales].[Orders](
[orderid] [int] IDENTITY(1,1) NOT NULL,
[custid] [int] NULL,
[empid] [int] NOT NULL,
[shipperid] [int] NOT NULL,
... )
Cột [custid], [empid], [shipperid]
là tham số corelated cho [Sales].[Customers], [HR].[Employees], [Sales].[Shippers]
phù hợp. Trong mỗi trường hợp, chúng ta có một chỉ mục được nhóm trên một cột được tham chiếu trong bảng parrent.
ALTER TABLE [Sales].[Orders] WITH CHECK ADD CONSTRAINT [FK_Orders_Customers] FOREIGN KEY([custid]) REFERENCES [Sales].[Customers] ([custid])
ALTER TABLE [Sales].[Orders] WITH CHECK ADD CONSTRAINT [FK_Orders_Employees] FOREIGN KEY([empid]) REFERENCES [HR].[Employees] ([empid])
ALTER TABLE [Sales].[Orders] WITH CHECK ADD CONSTRAINT [FK_Orders_Shippers] FOREIGN KEY([shipperid])REFERENCES [Sales].[Shippers] ([shipperid])
Tôi đang cố gắng để INSERT [Sales].[Orders] SELECT ... FROM
một bảng khác được gọi là [Sales].[OrdersCache]
có cấu trúc tương tự như [Sales].[Orders]
ngoại trừ khóa ngoại. Một điều quan trọng khác có thể đề cập đến bảng [Sales].[OrdersCache]
là một chỉ mục được nhóm.
CREATE CLUSTERED INDEX idx_c_OrdersCache ON Sales.OrdersCache ( custid, empid )
Như mong đợi khi tôi đang cố gắng chèn một khối lượng dữ liệu thấp LOOP THAM GIA hoạt động tốt, làm cho chỉ mục tìm kiếm trên các khóa ngoại.
Với khối lượng dữ liệu lớn, MERGE THAM GIA được sử dụng bởi trình tối ưu hóa truy vấn như một cách hiệu quả nhất để duy trì khóa foregn trong truy vấn.
Và không có gì để làm với nó ngoại trừ bằng cách sử dụng TÙY CHỌN (LOOP THAM GIA) trong trường hợp của chúng tôi với các khóa ngoại hoặc INNER LOOP THAM GIA trong trường hợp THAM GIA rõ ràng.
Dưới đây là truy vấn tôi đang cố gắng chạy trong môi trường của mình:
INSERT Sales.Orders (
custid, empid, shipperid, ... )
SELECT custid, empid, 2, ...
FROM Sales.OrdersCache
Nhìn vào kế hoạch, chúng ta có thể thấy rằng cả 3 khóa tìm kiếm được xác thực với MERGE THAM GIA. Nó không phải là một cách thích hợp cho tôi vì nó sử dụng INDEX SCAN với toàn bộ khóa chỉ mục.
Sử dụng TÙY CHỌN (LOOP THAM GIA) không phù hợp vì chi phí cao hơn gần 15% so với MERGE THAM GIA (Tôi nghĩ rằng hồi quy sẽ lớn hơn với khối lượng dữ liệu tăng lên).
Trong câu lệnh CHỌN, bạn có thể thấy giá trị đơn cho shipperid
thuộc tính cho toàn bộ tập hợp được chèn. Theo tôi, phải có một cách để làm cho giai đoạn xác nhận cho tập được chèn nhanh hơn ít nhất là cho thuộc tính bất biến. Cái gì đó như:
- làm cho LOOP THAM GIA, MERGE THAM GIA, HASH THAM GIA nếu chúng ta có tập hợp con không xác định để xác thực THAM GIA
- nếu chỉ có một giá trị rõ ràng duy nhất của cột được xác thực, chúng tôi chỉ thực hiện xác thực một lần (INDEX XEMK).
Có bất kỳ mẫu chung nào để vượt qua tình huống trên bằng cách sử dụng các cấu trúc mã, các đối tượng DDL bổ sung, v.v. không?
Đã thêm 20/07. Giải pháp. Trình tối ưu hóa truy vấn đã thực hiện tối ưu hóa xác thực 'khóa đơn - khóa ngoại' bằng cách sử dụng MERGE THAM GIA. Và chỉ tạo cho bảng Sales.Shippers, để lại LOOP THAM GIA cho một tham gia khác trong truy vấn cùng một lúc. Vì tôi có một vài hàng trong bảng cha Trình tối ưu hóa truy vấn sử dụng thuật toán nối kết hợp sắp xếp và so sánh mỗi hàng trong bảng bên trong với bảng cha chỉ một lần. Vì vậy, đó là câu trả lời cho câu hỏi của tôi nếu có bất kỳ cơ chế cụ thể nào để xử lý hiệu quả các giá trị đơn lẻ trong một tập hợp trong khi xác thực khóa đơn. Đó không phải là quyết định hoàn hảo nhưng đó là cách SQL Server tối ưu hóa trường hợp.
Hiệu suất điều tra cho thấy rằng trong trường hợp của tôi, câu lệnh chèn MERGE THAM GIA và LOOP THAM GIA đã trở nên xấp xỉ bằng 750 hàng được chèn đồng thời với ưu thế sau của MERGE THAM GIA (trong tài nguyên thời gian của CPU). Vì vậy, sử dụng TÙY CHỌN (LOOP THAM GIA) là một giải pháp thích hợp cho quy trình kinh doanh của tôi.