Bài đăng này là một phần của loạt bài viết về mục tiêu hàng. Bạn có thể tìm thấy các phần khác tại đây:
- Phần 1:Thiết lập và xác định mục tiêu hàng
- Phần 2:Bán tham gia
Phần này bao gồm khi nào và tại sao trình tối ưu hóa giới thiệu mục tiêu hàng cho kết hợp chống.
Giới thiệu
Một tham gia chống còn được gọi là một tham gia chống bán. Nó trả về từng hàng từ đầu vào tham gia A mà không khớp nào có thể được tìm thấy trên đầu vào B.
Để tham gia chống:
- Trình tối ưu hoá có thể thêm mục tiêu hàng bên trong vào áp dụng (tham gia các vòng lồng nhau có tương quan) chỉ chống tham gia .
- Mục tiêu hàng không được thêm vào cho các vòng lặp lồng nhau không tương quan, chống nối, băm chống nối hoặc hợp nhất chống nối.
- Như mọi khi, mọi mục tiêu hàng đều chỉ được thêm vào nếu nó thấp hơn ước tính mà không áp dụng mục tiêu hàng.
- Dự phòng bên trong
TOP
mệnh đề vàDISTINCT/GROUP BY
các thao tác có thể được đơn giản hóa đi.
Mở rộng ở gạch đầu dòng đầu tiên ở trên, sự khác biệt chính giữa áp dụng bán nối và áp dụng mục tiêu hàng chống nối là:
- Áp dụng kết hợp bán luôn có mục tiêu hàng (miễn là nó nhỏ hơn ước tính mà không có mục tiêu).
- Áp dụng kết hợp chống có thể làm nổi bật mục tiêu hàng , nhưng chỉ khi kết hợp chống hợp lý được chuyển thành áp dụng trong quá trình tối ưu hóa dựa trên chi phí .
Tôi xin lỗi vì những quy tắc này không đơn giản hơn, nhưng tôi đã không thực hiện chúng. Hy vọng rằng một số thảo luận và ví dụ sẽ làm cho tất cả rõ ràng hơn.
Không có mục tiêu hàng chống tham gia theo mặc định
Trình tối ưu hóa giả định rằng mọi người viết bán tham gia (gián tiếp, ví dụ:sử dụng EXISTS
) với kỳ vọng rằng hàng đang được tìm kiếm sẽ được tìm thấy . Một kết nối bán áp dụng mục tiêu hàng được đặt bằng trình tối ưu hóa để giúp nhanh chóng tìm thấy hàng phù hợp mong đợi đó.
Đối với chống tham gia (thể hiện, ví dụ:sử dụng NOT EXISTS
) giả định của trình tối ưu hóa là một hàng phù hợp sẽ không được tìm thấy . Áp dụng chống tham gia mục tiêu hàng không được đặt bởi trình tối ưu hóa, vì nó dự kiến phải kiểm tra tất cả các hàng để xác nhận không có hàng nào phù hợp.
Nếu hóa ra có một hàng phù hợp, thì phép nối chống áp dụng có thể mất nhiều thời gian hơn để xác định hàng này so với nếu mục tiêu hàng đã được sử dụng. Tuy nhiên, anti join vẫn sẽ kết thúc tìm kiếm ngay khi gặp phải trận đấu (không mong muốn).
Áp dụng các điều kiện mục tiêu của hàng chống tham gia
SQL Server không cung cấp cho chúng tôi cách viết một tham gia chống trực tiếp, vì vậy chúng tôi phải sử dụng các giải pháp thay thế như NOT EXISTS
, NOT IN/ANY/SOME
hoặc EXCEPT
. Mỗi biểu mẫu này dẫn đến một biểu diễn truy vấn con trong cây được phân tích cú pháp khi bắt đầu biên dịch truy vấn. Truy vấn con này luôn được hủy đăng ký thành một đơn đăng ký và sau đó được chuyển đổi thành một liên kết phản logic nếu có thể (các chi tiết tương tự như đối với semi join đã thảo luận ở phần 2). Tất cả điều này xảy ra trước khi một kế hoạch tầm thường được xem xét.
Để tham gia chống có được mục tiêu hàng, nó phải nhập tối ưu hóa dựa trên chi phí như một liên kết chống hợp lý (có nghĩa là chuyển đổi từ một ứng dụng ở trên phải đã thành công). Sau đó, trình tối ưu hóa dựa trên chi phí phải chọn triển khai liên kết chống hợp lý dưới dạng áp dụng . Để điều này xảy ra, trước tiên trình tối ưu hóa phải chọn khám phá tùy chọn áp dụng; thì nó phải chọn đó là lựa chọn rẻ nhất (cho phần đó của kế hoạch).
Mục tiêu hàng chống liên kết được đặt bởi bất kỳ một trong các quy tắc tối ưu hóa dựa trên chi phí có thể chuyển đổi một liên kết thành áp dụng. Tham gia chống lại tham gia tối ưu hóa dựa trên chi phí khi áp dụng (bởi vì chuyển đổi thành liên kết chống lôgic không thành công) sẽ không có một mục tiêu hàng được áp dụng.
Trình tối ưu hóa dựa trên chi phí sẽ chỉ khám phá và chọn tùy chọn kết hợp để áp dụng nếu có một cách hiệu quả để xác định bất kỳ hàng bên trong phù hợp nào (ví dụ:sử dụng chỉ mục). Trình tối ưu hóa sẽ không khám phá tùy chọn nếu cây con nối bên trong thiếu bất kỳ thứ gì hữu ích cho vị từ áp dụng để "chốt vào". Đây có thể là một chỉ mục, chỉ mục tạm thời (thông qua một cuộn chỉ mục háo hức) hoặc khóa logic khác. Việc thêm mục tiêu hàng sẽ giúp trình tối ưu hóa đánh giá chi phí của tùy chọn kết hợp để áp dụng cho rằng cần phải đặt tối đa một hàng.
Lưu ý rằng một phép nối chống áp dụng có thể xuất hiện trong một kế hoạch thực thi mà không có mục tiêu hàng. Điều này xảy ra khi chuyển đổi ban đầu từ áp dụng sang kết hợp không thành công, điều này tương đối phổ biến. Khi điều này xảy ra, liên kết chống bắt đầu hoạt động trong trình tối ưu hóa dựa trên chi phí khi áp dụng và do đó, không bao giờ có mục tiêu hàng được thêm bởi một trong các quy tắc tham gia để áp dụng.
Tất nhiên, một mục tiêu hàng cũng có thể được giới thiệu ở phía bên trong của áp dụng này thông qua một cơ chế khác (không liên quan đến áp dụng), ví dụ:bởi một toán tử Hàng đầu riêng biệt.
Tóm lại:
- Kết hợp chống chỉ có thể đạt được mục tiêu hàng trong quá trình tối ưu hóa dựa trên chi phí (CBO).
- Các quy tắc chuyển một liên kết chống thành một áp dụng sẽ thêm một mục tiêu hàng.
- Tham gia chống phải tham gia CBO với tư cách tham gia, không phải đơn đăng ký.
- Để nhập CBO dưới dạng một phép nối, các giai đoạn trước đó phải có thể viết lại truy vấn con dưới dạng một phép nối (thông qua một giai đoạn áp dụng).
- CBO chỉ khám phá phép liên kết để áp dụng chuyển đổi trong các trường hợp có triển vọng.
Ví dụ
Sẽ khó hơn một chút khi chứng minh tất cả những điều này cho việc apply anti join so với trường hợp apply semi join. Lý do cho điều này sẽ được đề cập trong phần 4.
Trong khi đó, đây là một ví dụ của AdventureWorks cho thấy cách áp dụng kết hợp chống với mục tiêu hàng phát sinh, sử dụng cùng các cờ theo dõi không có tài liệu như đối với tham gia bán. Cờ theo dõi 8608 được thêm vào để hiển thị cấu trúc bản ghi nhớ ban đầu khi bắt đầu tối ưu hóa dựa trên chi phí.
SELECT P.ProductID FROM Production.Product AS P WHERE NOT EXISTS ( SELECT 1 FROM Production.TransactionHistoryArchive AS THA WHERE THA.ProductID = P.ProductID UNION ALL SELECT 1 FROM Production.TransactionHistory AS TH WHERE TH.ProductID = P.ProductID ) OPTION (QUERYTRACEON 3604, QUERYTRACEON 8607, QUERYTRACEON 8608, QUERYTRACEON 8612, QUERYTRACEON 8621);
Truy vấn con tồn tại trước tiên được chuyển đổi thành apply:
Đơn đăng ký sau đó được viết lại thành công dưới dạng một phép nối (trong trường hợp này):
Bản ghi nhớ ban đầu hiển thị liên kết chống hợp lý được trình bày cho trình tối ưu hóa dựa trên chi phí (chỉ nhóm gốc được hiển thị cho ngắn gọn):
Cây đầu ra của trình tối ưu hóa là:
Lưu ý rằng phép nối chống logic đầu vào đã được thực hiện như một phép nối chống áp dụng. Mục tiêu hàng là 1 đã được đặt cho toán tử Kết nối và mỗi người trong số hai bảng đều truy cập.
Kế hoạch thực hiện ước tính cho thấy một liên kết chống áp dụng với một hàng được ước tính ở phía bên trong của liên kết chống cho mỗi hàng bên ngoài:
Đối với những người sử dụng SQL Server 2017 CU3 và SSMS 17.5, cửa sổ Thuộc tính cho từng toán tử Kết hợp và Tìm kiếm Chỉ mục ở trên sẽ hiển thị Ước tínhRowsWithoutRowGoal giá trị tương ứng với giá trị bản số được hiển thị trong đầu ra cờ theo dõi. Thuộc tính này không hiển thị trong chú giải công cụ và chỉ bị bỏ qua đối với các toán tử không có mục tiêu hàng. Cá nhân tôi nghĩ rằng sẽ hữu ích nếu thêm một số bóng mờ vào các vùng của kế hoạch bị ảnh hưởng bởi mục tiêu hàng, vì vậy chúng tôi sẽ không cần phải nhấp vào từng toán tử riêng lẻ.
Những độc giả tinh ý có thể nhận thấy rằng cây đầu ra của trình tối ưu hóa hiển thị bảng Lưu trữ được truy cập đầu tiên, sau đó là bảng Lịch sử. Kế hoạch đồ họa có chúng theo cách khác. Việc viết lại sau tối ưu hóa xem xét sắp xếp lại thứ tự các đầu vào cho toán tử Kết hợp trên cơ sở chi phí dự kiến. Trong trường hợp này, các bảng được sắp xếp lại trong kế hoạch cuối cùng vì quyền truy cập vào bảng Lịch sử dự kiến sẽ rẻ hơn (0,0850383 đơn vị) so với truy cập bảng Lưu trữ (0,085441 đơn vị). Việc tối ưu hóa này chỉ diễn ra khi có mục tiêu hàng đơn như tôi đã mô tả trong UNION ALL Optimization. Bạn cũng cần chạy SQL Server 2008 R2 trở xuống, các phiên bản vá lỗi của SQL Server 2014 và 2016 có bật cờ theo dõi 4199 hoặc SQL Server 2017.
Tóm tắt
Một phép nối bán áp dụng luôn đi kèm với một mục tiêu hàng ở phía bên trong của nó. Trình tối ưu hóa giả định rằng một hàng phù hợp tồn tại, vì vậy, có thể đáng giá khi đặt mục tiêu hàng để định vị hàng đó một cách nhanh chóng. Mục tiêu hàng cũng phản ánh thực tế là sẽ gặp phải tối đa một hàng cho mỗi lần lặp lại vòng lặp.
Để áp dụng kết hợp chống, mục tiêu hàng không được đặt theo mặc định. Giả định của trình tối ưu hóa đối với kết hợp chống là một hàng phù hợp sẽ không được tìm thấy, vì vậy sẽ phản tác dụng nếu đặt mục tiêu hàng. Một phần của kế hoạch cần sử dụng tất cả các hàng không được hưởng lợi từ logic mục tiêu hàng.
Tuy nhiên, mục tiêu hàng vẫn có thể được đặt cho một phép nối chống áp dụng trong quá trình tối ưu hóa dựa trên chi phí. Điều này chỉ xảy ra khi trình tối ưu hóa xem xét việc viết lại một liên kết chống hợp lý cho một đơn đăng ký. Một phép chống nối lôgic (được viết bằng cú pháp T-SQL gián tiếp) không thể được viết lại dưới dạng một phép nối chống thông thường (không tương quan) trước khi bắt đầu tối ưu hóa dựa trên chi phí sẽ không có mục tiêu hàng.
Đối với các quy tắc có thể chuyển đổi phép nối chống hợp lý thành phép nối chống áp dụng để so khớp, phải có một cách hợp lý để xác định vị trí bất kỳ hàng phù hợp nào ở phía bên trong của phép nối. Nói cách khác, phải có một số lợi ích tiềm năng khi đẩy vị từ nối xuống.
Phần cuối cùng của loạt bài này sẽ xem xét kỹ một hình dạng kế hoạch thực hiện chống tham gia mà tôi coi là một mô hình chống.