Khắc phục MERGE THAM GIA (INDEX SCAN) với giá trị KEY duy nhất rõ ràng trên KEY NGOẠI TỆ


9

Đã 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 ... FROMmộ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. THAM GIA MERGE trong quá trình xác nhận khóa ngoại

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 shipperidthuộ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.

Câu trả lời:


8

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ỷ lệ phần trăm chi phí được hiển thị trong đầu ra showplan luôn là ước tính mô hình tối ưu hóa, ngay cả trong kế hoạch hậu thực hiện (thực tế). Những chi phí này có thể không phản ánh hiệu suất thời gian chạy thực tế trên phần cứng cụ thể của bạn. Cách duy nhất để chắc chắn là kiểm tra các lựa chọn thay thế với khối lượng công việc của bạn, đo bất kỳ số liệu nào là quan trọng nhất đối với bạn (thời gian trôi qua, sử dụng CPU, v.v.).

Theo kinh nghiệm của tôi, trình tối ưu hóa chuyển từ các vòng lặp tham gia để hợp nhất tham gia để xác thực khóa ngoại quá sớm. Trong tất cả các hoạt động ngoại trừ lớn nhất, tôi đã tìm thấy các vòng lặp tham gia là thích hợp hơn. Và bởi "lớn", ý tôi là ít nhất hàng chục triệu hàng, chắc chắn không phải là hàng ngàn hoặc do đó bạn chỉ ra trong các bình luận cho câu hỏi của bạ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.

Điều này có ý nghĩa về nguyên tắc, nhưng ngày nay không có logic như vậy trong logic xây dựng kế hoạch mà xác nhận khóa ngoài sử dụng. Logic hiện tại cố tình rất chung chung và trực giao với truy vấn rộng hơn; tối ưu hóa cụ thể làm phức tạp việc kiểm tra và tăng khả năng xảy ra lỗi cạnh.

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?

Không phải là tôi biết. Rủi ro bế tắc với xác nhận hợp nhất tham gia khóa ngoại được biết đến , với cách giải quyết được sử dụng rộng rãi nhất là OPTION (LOOP JOIN)gợi ý. Không có cách nào để tránh các khóa chia sẻ được thực hiện trong quá trình xác thực khóa ngoại, bởi vì những khóa này được yêu cầu cho tính chính xác , ngay cả dưới các mức cách ly phiên bản hàng.

Không có câu trả lời chung nào tốt hơn (so với gợi ý nối vòng lặp) nếu bạn muốn giữ lại khả năng cho nhiều quy trình đồng thời để thêm hàng vào bảng cha và bảng con một cách giao dịch. Nhưng, nếu bạn sẵn sàng tuần tự hóa các sửa đổi dữ liệu (không đọc), sử dụng sp_getapplock là một kỹ thuật đơn giản và đáng tin cậy.

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.