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 phần đầu tiên tại đây:
- Phần 1:Thiết lập và xác định mục tiêu hàng
Việc sử dụng TOP
tương đối nổi tiếng hoặc một FAST n
gợi ý truy vấn có thể đặt mục tiêu hàng trong kế hoạch thực thi (xem Đặt và xác định mục tiêu hàng trong kế hoạch thực thi nếu bạn cần cập nhật về mục tiêu hàng và nguyên nhân của chúng). Ít được đánh giá cao hơn là kết hợp bán (và liên kết chống) cũng có thể giới thiệu mục tiêu hàng, mặc dù điều này có phần ít khả năng hơn so với trường hợp của TOP
, FAST
và SET ROWCOUNT
.
Bài viết này sẽ giúp bạn hiểu khi nào và tại sao, một phép nối bán phần gọi ra logic mục tiêu hàng của trình tối ưu hóa.
Semi tham gia
Một phép nối bán trả về một hàng từ một đầu vào phép nối (A) nếu có ít nhất một phù hợp với hàng trên đầu vào kết hợp khác (B).
Sự khác biệt cơ bản giữa phép nối bán phần và phép nối thông thường là:
- Kết nối Semi trả về từng hàng từ đầu vào A hoặc không. Không có sự trùng lặp hàng có thể xảy ra.
- Phép nối thông thường trùng lặp các hàng nếu có nhiều kết quả khớp trên vị từ phép nối.
- Nối bán phần được định nghĩa để chỉ trả về các cột từ đầu vào A.
- Phép nối thông thường có thể trả về các cột từ một trong hai (hoặc cả hai) đầu vào phép nối.
T-SQL hiện thiếu hỗ trợ cho cú pháp trực tiếp như FROM A SEMI JOIN B ON A.x = B.y
, vì vậy chúng tôi cần sử dụng các hình thức gián tiếp như EXISTS
, SOME/ANY
(bao gồm cả viết tắt tương đương IN
để so sánh bình đẳng) và đặt INTERSECT
.
Mô tả của kết hợp bán ở trên gợi ý tự nhiên về việc áp dụng mục tiêu hàng, vì chúng tôi quan tâm đến việc tìm bất kỳ hàng nào phù hợp trong B, không phải tất cả các hàng như vậy . Tuy nhiên, một phép nối bán logic được thể hiện trong T-SQL có thể không dẫn đến một kế hoạch thực thi sử dụng mục tiêu hàng vì một số lý do, mà chúng tôi sẽ giải nén tiếp theo.
Chuyển đổi và đơn giản hóa
Một phép nối bán logic có thể được đơn giản hóa hoặc thay thế bằng một cái gì đó khác trong quá trình biên dịch và tối ưu hóa truy vấn. Ví dụ AdventureWorks bên dưới cho thấy một kết nối bán bị xóa hoàn toàn do mối quan hệ khóa ngoại đáng tin cậy:
CHỌN TH.ProductID TỪ Production.TransactionHistory AS THWHERE TH.ProductID IN (CHỌN P.ProductID TỪ Production.Product AS P);
Khóa ngoại đảm bảo rằng Product
các hàng sẽ luôn tồn tại cho mỗi hàng Lịch sử. Do đó, kế hoạch thực thi chỉ truy cập vào TransactionHistory
bảng:
Một ví dụ phổ biến hơn được thấy khi phép nối bán có thể được chuyển đổi thành phép nối bên trong. Ví dụ:
CHỌN P.ProductID TỪ SẢN XUẤT. Sản phẩm AS P WHERE TỒN TẠI (CHỌN * TỪ Sản xuất.ProductInventory AS INV WHERE INV.ProductID =P.ProductID);
Kế hoạch thực thi cho thấy rằng trình tối ưu hóa đã giới thiệu một tập hợp (nhóm trên INV.ProductID
) để đảm bảo rằng phép nối bên trong chỉ có thể trả về Product
các hàng một lần hoặc hoàn toàn không (theo yêu cầu để bảo toàn ngữ nghĩa của phép nối bán phần):
Việc chuyển đổi sang liên kết bên trong được khám phá sớm bởi vì trình tối ưu hóa biết nhiều thủ thuật hơn đối với các liên kết bên trong hơn là đối với các liên kết bán, có khả năng dẫn đến nhiều cơ hội tối ưu hóa hơn. Đương nhiên, lựa chọn kế hoạch cuối cùng vẫn là một quyết định dựa trên chi phí trong số các lựa chọn thay thế đã được khám phá.
Tối ưu hóa sớm
Mặc dù T-SQL thiếu SEMI JOIN
trực tiếp cú pháp, trình tối ưu hóa biết tất cả về kết nối bán nguyên bản và có thể thao tác trực tiếp với chúng. Các cú pháp bán kết nối giải pháp chung được chuyển đổi thành một kết nối bán nội bộ "thực" ngay từ đầu trong quá trình biên dịch truy vấn (trước cả khi một kế hoạch tầm thường được xem xét).
Hai nhóm cú pháp giải pháp chính là EXISTS/INTERSECT
và ANY/SOME/IN
. EXISTS
và INTERSECT
các trường hợp chỉ khác nhau ở chỗ cái sau đi kèm với DISTINCT
ngầm hiểu (nhóm trên tất cả các cột dự kiến). Cả EXISTS
và INTERSECT
được phân tích cú pháp dưới dạng EXISTS
với truy vấn con tương quan. ANY/SOME/IN
tất cả các biểu diễn đều được hiểu là một phép toán MỘT SỐ. Chúng ta có thể khám phá sớm hoạt động tối ưu hóa này với một vài cờ theo dõi không có tài liệu, những cờ này sẽ gửi thông tin về hoạt động của trình tối ưu hóa đến tab thông báo SSMS.
Ví dụ, kết nối bán mà chúng tôi đang sử dụng cho đến nay cũng có thể được viết bằng IN
:
CHỌN P.ProductIDFROM Production.Product AS PWHERE P.ProductID IN / * hoặc =ANY / SOME * / (SELECT TH.ProductID FROM Production.TransactionHistory AS TH) TÙY CHỌN (QUERYTRACEON 3604, QUERYTRACEON 8606, QUERYTRACEON 8621);
Cây đầu vào của trình tối ưu hóa như sau:
Toán tử vô hướng ScaOp_SomeComp là SOME
so sánh vừa đề cập ở trên. Mã 2 là mã cho kiểm tra bình đẳng, vì IN
tương đương với = SOME
. Nếu bạn quan tâm, có các mã từ 1 đến 6 đại diện cho (<, =, <=,>,! =,> =) Toán tử so sánh tương ứng.
Quay lại EXISTS
cú pháp mà tôi thích sử dụng thường xuyên nhất để diễn đạt gián tiếp một phép nối bán phần:
CHỌN P.ProductIDFROM Production.Product AS PWHERE EXISTS (SELECT * FROM Production.TransactionHistory AS TH WHERE TH.ProductID =P.ProductID) TÙY CHỌN (QUERYTRACEON 3604, QUERYTRACEON 8606, QUERYTRACEON 8621);
Cây đầu vào của trình tối ưu hóa là:
Cây đó là một bản dịch khá trực tiếp của văn bản truy vấn; mặc dù lưu ý rằng SELECT *
đã được thay thế bằng phép chiếu của giá trị số nguyên không đổi 1 (xem dòng văn bản áp chót).
Điều tiếp theo mà trình tối ưu hóa làm là hủy thiết lập truy vấn con trong lựa chọn quan hệ (=bộ lọc) bằng cách sử dụng quy tắc RemoveSubqInSel . Trình tối ưu hóa luôn làm điều này, vì nó không thể hoạt động trực tiếp trên các truy vấn con. Kết quả là áp dụng (a.k.a liên kết tương quan hoặc liên kết bên):
(Cùng một quy tắc loại bỏ truy vấn con tạo ra cùng một đầu ra cho SOME
cây đầu vào).
Bước tiếp theo là viết lại đơn đăng ký như một kết hợp thông thường bằng cách sử dụng Trình xử lý ứng dụng gia đình trị. Đây là điều mà trình tối ưu hóa luôn cố gắng thực hiện, vì nó có nhiều quy tắc khám phá cho các phép nối hơn là áp dụng. Không phải mọi đơn đăng ký đều có thể được viết lại dưới dạng liên kết, nhưng ví dụ hiện tại rất đơn giản và thành công:
Lưu ý loại kết nối là trái bán. Thật vậy, đây chính xác là cây mà chúng ta sẽ nhận được ngay lập tức nếu T-SQL hỗ trợ cú pháp như:
CHỌN P.ProductID TỪ SẢN XUẤT. Sản phẩm NHƯ P TRÁI GIAI ĐOẠN THAM GIA Sản xuất.TransactionHistory AS TH TRÊN TH.ProductID =P.ProductID;
Thật là tuyệt nếu có thể diễn đạt các truy vấn trực tiếp hơn như thế này. Dù sao, độc giả quan tâm được khuyến khích khám phá các hoạt động đơn giản hóa ở trên với các cách khác tương đương về mặt logic để viết phép nối bán phần này trong T-SQL.
Bài học quan trọng ở giai đoạn này là trình tối ưu hóa luôn xóa các truy vấn phụ , thay thế chúng bằng một đơn đăng ký. Sau đó, nó cố gắng viết lại đơn đăng ký như một lần tham gia bình thường để tối đa hóa cơ hội tìm được một kế hoạch tốt. Hãy nhớ rằng tất cả những điều trước diễn ra trước khi một kế hoạch tầm thường được xem xét. Trong quá trình tối ưu hóa dựa trên chi phí, trình tối ưu hóa cũng có thể xem xét chuyển đổi kết hợp trở lại áp dụng.
Hash and Merge Semi Tham gia
SQL Server có sẵn ba tùy chọn triển khai vật lý chính cho một phép nối bán lôgic. Miễn là có một vị từ tương đương, các phép nối băm và hợp nhất có sẵn; cả hai đều có thể hoạt động ở các chế độ kết hợp trái và phải bán. Phép nối các vòng lặp lồng nhau chỉ hỗ trợ phép nối bán phần bên trái (không phải), nhưng không yêu cầu một vị từ tương đương. Hãy xem xét các tùy chọn vật lý băm và hợp nhất cho truy vấn mẫu của chúng ta (lần này được viết dưới dạng một tập hợp giao nhau):
CHỌN P.ProductID TỪ SẢN XUẤT. Sản phẩm AS PINTERSECTSELECT TH.ProductID TỪ Sản xuất.TransactionHistory AS TH;
Trình tối ưu hóa có thể tìm thấy một kế hoạch cho tất cả bốn kết hợp (trái / phải) và (băm / hợp nhất) bán kết hợp cho truy vấn này:
Điều đáng nói là ngắn gọn tại sao trình tối ưu hóa có thể xem xét cả kết nối trái và phải cho mỗi loại kết nối. Đối với tham gia bán băm, một vấn đề cần cân nhắc về chi phí chính là kích thước ước tính của bảng băm, luôn là đầu vào bên trái (phía trên) ban đầu. Đối với phép nối bán hợp nhất, các thuộc tính của mỗi đầu vào xác định xem phép hợp nhất một-nhiều hoặc nhiều-nhiều ít hiệu quả hơn với bảng làm việc sẽ được sử dụng.
Có thể rõ ràng từ các kế hoạch thực thi ở trên rằng cả phép băm hoặc kết hợp bán hợp nhất đều không được hưởng lợi từ việc đặt mục tiêu hàng . Cả hai kiểu nối luôn kiểm tra vị từ nối tại chính phép nối và nhằm tiêu thụ tất cả các hàng từ cả hai đầu vào để trả về tập kết quả đầy đủ. Điều đó không có nghĩa là tối ưu hóa hiệu suất không tồn tại cho phép ghép băm và phép nối nói chung - ví dụ:cả hai đều có thể sử dụng bitmap để giảm số lượng hàng tiếp cận với phép nối. Thay vào đó, vấn đề là một mục tiêu hàng trên một trong hai đầu vào sẽ không làm cho phép băm hoặc kết hợp bán kết hợp hiệu quả hơn.
Các vòng lặp lồng nhau và Áp dụng Bán tham gia
Loại kết nối vật lý còn lại là các vòng lồng nhau, có hai loại:vòng lặp lồng nhau thông thường (không tương quan) và áp dụng vòng lặp lồng nhau (đôi khi còn được gọi là vòng lặp tương quan hoặc bên tham gia).
Tham gia các vòng lặp lồng nhau thông thường tương tự như tham gia băm và hợp nhất ở chỗ vị từ nối được đánh giá tại tham gia. Như trước đây, điều này có nghĩa là không có giá trị trong việc đặt mục tiêu hàng trên một trong hai đầu vào. Đầu vào bên trái (phía trên) cuối cùng sẽ luôn được sử dụng hết và đầu vào bên trong không có cách nào để xác định (các) hàng nào nên được ưu tiên, vì chúng tôi không thể biết liệu một hàng có tham gia hay không cho đến khi vị từ được kiểm tra tại phép nối .
Ngược lại, một phép nối vòng lặp lồng nhau áp dụng có một hoặc nhiều tham chiếu bên ngoài (các tham số tương quan) tại phép nối, với vị từ tham gia được đẩy xuống mặt trong (phía dưới) của phép nối. Điều này tạo cơ hội cho việc áp dụng mục tiêu hàng một cách hữu ích. Nhớ lại rằng phép nối bán phần chỉ yêu cầu chúng ta kiểm tra sự tồn tại của một hàng trên đầu vào tham gia B khớp với hàng hiện tại trên đầu vào kết nối A (bây giờ hãy nghĩ về các chiến lược tham gia vòng lặp lồng nhau).
Nói cách khác, trên mỗi lần lặp lại một lần áp dụng, chúng ta có thể ngừng xem xét đầu vào B ngay khi tìm thấy kết quả phù hợp đầu tiên, bằng cách sử dụng vị từ nối được đẩy xuống. Đây chính xác là loại mục tiêu hàng có lợi cho việc tạo:tạo một phần của kế hoạch được tối ưu hóa để trả về n hàng phù hợp đầu tiên một cách nhanh chóng (trong đó n = 1
tại đây).
Tất nhiên, một bàn thắng liên tiếp có thể là một điều tốt hoặc không, tùy thuộc vào hoàn cảnh. Không có gì đặc biệt về mục tiêu hàng bán tham gia về mặt đó. Hãy xem xét một tình huống trong đó phía bên trong của phép nối bán phức tạp hơn một lần truy cập bảng đơn giản, có lẽ là phép nối nhiều bảng. Đặt mục tiêu hàng có thể giúp trình tối ưu hóa chọn chiến lược điều hướng hiệu quả chỉ cho cây con cụ thể đó , tìm hàng phù hợp đầu tiên để thỏa mãn kết nối bán thông qua các phép nối vòng lặp lồng nhau và tìm kiếm chỉ mục. Nếu không có mục tiêu hàng, trình tối ưu hóa có thể tự nhiên chọn băm hoặc hợp nhất các phép nối với các loại để giảm thiểu chi phí dự kiến của việc trả lại tất cả các hàng có thể có. Lưu ý rằng có một giả định ở đây, cụ thể là mọi người thường viết kết nối bán với kỳ vọng rằng trên thực tế tồn tại một hàng phù hợp với điều kiện tìm kiếm. Đây có vẻ là một giả định đủ công bằng đối với tôi.
Dù vậy, điểm quan trọng ở giai đoạn này là: Chỉ áp dụng tham gia vòng lặp lồng nhau có mục tiêu hàng được áp dụng bởi trình tối ưu hóa (mặc dù vậy hãy nhớ rằng mục tiêu hàng để áp dụng tham gia vòng lặp lồng nhau chỉ được thêm vào nếu mục tiêu hàng nhỏ hơn ước tính mà không có mục tiêu đó). Chúng tôi sẽ xem xét một số ví dụ đã làm để hy vọng làm rõ tất cả điều này tiếp theo.
Ví dụ về bán kết nối các vòng lặp lồng nhau
Tập lệnh sau tạo hai bảng tạm thời trong đống. Đầu tiên có các số từ 1 đến 20 bao gồm; cái kia có 10 bản sao của mỗi số trong bảng đầu tiên:
DROP TABLE NẾU TỒN TẠI # E1, # E2; TẠO BẢNG # E1 (c1 số nguyên NULL); TẠO BẢNG # E2 (c1 số nguyên NULL); INSERT # E1 (c1) CHỌN SV.numberFROM master.dbo.spt_values AS SVWHERE SV. [Type] =N'P 'AND SV.number> =1 AND SV.number <=20; INSERT # E2 (c1) SELECT (SV.number% 20) + 1FROM master.dbo.spt_values AS SVWHERE SV. [Type] =N'P 'AND SV.number> =1 AND SV.number <=200;Không có chỉ mục và số lượng hàng tương đối nhỏ, trình tối ưu hóa chọn triển khai các vòng lặp lồng nhau (thay vì băm hoặc hợp nhất) cho truy vấn kết nối bán sau). Các cờ theo dõi không có tài liệu cho phép chúng tôi xem thông tin mục tiêu hàng và cây đầu ra của trình tối ưu hóa:
CHỌN E1.c1 TỪ # E1 NHƯ E1WHERE E1.c1 TRONG (CHỌN E2.c1 TỪ # E2 NHƯ E2) TÙY CHỌN (QUERYTRACEON 3604, QUERYTRACEON 8607, QUERYTRACEON 8612);Kế hoạch thực thi ước tính có phép nối các vòng lặp lồng nhau bán nối, với 200 hàng mỗi lần quét toàn bộ bảng
#E2
. 20 lần lặp lại của vòng lặp đưa ra ước tính tổng cộng là 4.000 hàng:
Các thuộc tính của toán tử vòng lặp lồng nhau cho thấy rằng vị từ được áp dụng tại phép nối nghĩa là đây là một tham gia vòng lặp lồng nhau không có liên quan :
Đầu ra cờ theo dõi (trên tab thông báo SSMS) hiển thị kết nối bán vòng lồng nhau và không có mục tiêu hàng (RowGoal 0):
Lưu ý rằng kế hoạch sau thực thi cho truy vấn đồ chơi này sẽ không hiển thị tổng cộng 4.000 hàng được đọc từ bảng # E2. Phép nối bán vòng lặp lồng nhau (có tương quan hoặc không) sẽ ngừng tìm kiếm thêm hàng ở phía bên trong (mỗi lần lặp) ngay sau khi gặp kết quả khớp đầu tiên cho hàng bên ngoài hiện tại. Bây giờ, thứ tự của các hàng gặp phải từ quá trình quét đống # E2 trên mỗi lần lặp là không xác định (và có thể khác nhau trên mỗi lần lặp), vì vậy về nguyên tắc hầu như tất cả các hàng đều có thể được kiểm tra trên mỗi lần lặp, trong trường hợp gặp phải hàng phù hợp càng muộn càng tốt (hoặc thực sự, trong trường hợp không có hàng nào phù hợp, hoàn toàn không phải).
Ví dụ:nếu chúng tôi giả sử triển khai thời gian chạy trong đó các hàng tình cờ được quét theo cùng một thứ tự (ví dụ:"thứ tự chèn") mỗi lần, tổng số hàng được quét trong ví dụ đồ chơi này sẽ là 20 hàng trong lần lặp đầu tiên, 1 hàng ở lần lặp thứ hai, 2 hàng ở lần lặp thứ ba, v.v. với tổng số 20 + 1 + 2 + (…) + 19 =210 hàng. Thật vậy, bạn có nhiều khả năng quan sát được tổng số này, điều này nói lên nhiều hạn chế của mã trình diễn đơn giản hơn là về bất kỳ điều gì khác. Người ta không thể dựa vào thứ tự của các hàng được trả về từ một phương thức truy cập không có thứ tự mà người ta có thể dựa vào đầu ra có thứ tự rõ ràng từ một truy vấn mà không có
ORDER BY
cấp cao nhất mệnh đề.Đăng ký Semi Tham gia
Bây giờ chúng tôi tạo một chỉ mục không phân biệt trên bảng lớn hơn (để khuyến khích trình tối ưu hóa chọn một kết nối bán áp dụng) và chạy lại truy vấn:
TẠO CHỈ SỐ KHÔNG ĐƯỢC ĐIỀU CHỈNH nc1 ON # E2 (c1); CHỌN E1.c1 TỪ # E1 NHƯ E1VÀ E1.c1 TRONG (CHỌN E2.c1 TỪ # E2 NHƯ E2) TÙY CHỌN (QUERYTRACEON 3604, QUERYTRACEON 8607, QUERYTRACEON 8612);Kế hoạch thực thi hiện có tính năng nối bán áp dụng, với 1 hàng cho mỗi lần tìm kiếm chỉ mục (và 20 lần lặp lại như trước đây):
Chúng tôi có thể nói rằng đó là một áp dụng bán tham gia bởi vì các thuộc tính nối hiển thị một tham chiếu bên ngoài chứ không phải là một vị từ nối:
Vị từ kết hợp đã được đẩy xuống mặt bên trong của ứng dụng và khớp với chỉ mục mới:
Mỗi lần tìm kiếm được mong đợi trả về 1 hàng, mặc dù thực tế là mỗi giá trị được nhân đôi 10 lần trong bảng đó; đây là ảnh hưởng của mục tiêu hàng . Mục tiêu hàng sẽ dễ dàng xác định hơn trên các bản dựng SQL Server hiển thị EstimRowsWithoutRowGoal thuộc tính kế hoạch (SQL Server 2017 CU3 tại thời điểm viết bài). Trong phiên bản sắp tới của Plan Explorer, điều này cũng sẽ được hiển thị trên chú giải công cụ cho các nhà khai thác liên quan:
Đầu ra cờ theo dõi là:
Toán tử vật lý đã thay đổi từ một phép nối vòng thành một phép áp dụng chạy ở chế độ nối nửa bên trái. Truy cập vào bảng
#E2
đã đạt được mục tiêu hàng là 1 (bản số không có mục tiêu hàng được hiển thị là 10). Mục tiêu hàng không phải là một vấn đề lớn trong trường hợp này vì chi phí truy xuất ước tính mười hàng cho mỗi lần tìm kiếm không nhiều hơn một hàng. Vô hiệu hóa mục tiêu hàng cho truy vấn này (sử dụng cờ theo dõi 4138 hoặcDISABLE_OPTIMIZER_ROWGOAL
gợi ý truy vấn) sẽ không thay đổi hình dạng của kế hoạch.Tuy nhiên, trong các truy vấn thực tế hơn, việc giảm chi phí do mục tiêu hàng bên trong có thể tạo ra sự khác biệt giữa các tùy chọn triển khai cạnh tranh. Ví dụ:việc vô hiệu hóa mục tiêu hàng có thể khiến trình tối ưu hóa thay vào đó chọn một liên kết băm hoặc hợp nhất bán hoặc bất kỳ một trong nhiều tùy chọn khác được xem xét cho truy vấn. Nếu không có gì khác, mục tiêu hàng ở đây phản ánh chính xác thực tế là một phép nối bán áp dụng sẽ ngừng tìm kiếm bên trong ngay khi tìm thấy kết quả phù hợp đầu tiên và chuyển sang hàng bên ngoài tiếp theo.
Lưu ý rằng các bản sao đã được tạo trong bảng
#E2
để mục tiêu áp dụng hàng bán kết hợp (1) sẽ thấp hơn ước tính bình thường (10, từ thông tin mật độ thống kê). Nếu không có bản sao, ước tính hàng cho mỗi lần tìm kiếm thành#E2
cũng sẽ là 1 hàng, vì vậy mục tiêu hàng là 1 sẽ không được áp dụng (hãy nhớ quy tắc chung về điều này!)Mục tiêu hàng so với Hàng đầu
Cho rằng các kế hoạch thực thi hoàn toàn không chỉ ra sự hiện diện của mục tiêu hàng trước SQL Server 2017 CU3, người ta có thể nghĩ rằng việc triển khai tối ưu hóa này bằng cách sử dụng toán tử Top rõ ràng, thay vì thuộc tính ẩn như mục tiêu hàng sẽ rõ ràng hơn. Ý tưởng sẽ là chỉ cần đặt toán tử Top (1) ở phía bên trong của phép nối áp dụng bán / chống thay vì đặt mục tiêu hàng tại chính phép nối đó.
Sử dụng toán tử Top theo cách này sẽ không hoàn toàn không có tiền lệ. Ví dụ:đã có một phiên bản đặc biệt của Top được gọi là top đếm hàng được thấy trong kế hoạch thực thi sửa đổi dữ liệu khi
SET ROWCOUNT
khác 0 đang có hiệu lực (lưu ý rằng cách sử dụng cụ thể này đã không được dùng nữa kể từ năm 2005 mặc dù nó vẫn được phép trong SQL Server 2017). Việc triển khai số lượng hàng trên cùng có một chút rắc rối ở chỗ toán tử hàng đầu luôn được hiển thị dưới dạng Hàng đầu (0) trong kế hoạch thực thi, bất kể giới hạn số hàng thực tế có hiệu lực.Không có lý do thuyết phục nào khiến mục tiêu hàng nối bán áp dụng không thể được thay thế bằng toán tử Trên cùng (1) rõ ràng. Điều đó nói rằng, có một số lý do để thích không làm điều đó:
- Việc thêm một Đầu (1) rõ ràng đòi hỏi nhiều nỗ lực mã hóa và thử nghiệm của trình tối ưu hóa hơn là thêm một mục tiêu hàng (đã được sử dụng cho những thứ khác).
- Top không phải là một toán tử quan hệ; trình tối ưu hóa có ít hỗ trợ cho việc lập luận về nó. Điều này có thể tác động tiêu cực đến chất lượng kế hoạch bằng cách hạn chế khả năng của trình tối ưu hóa trong việc chuyển đổi các phần của kế hoạch truy vấn, ví dụ:bằng cách di chuyển các tập hợp, liên kết, bộ lọc và liên kết xung quanh.
- Nó sẽ giới thiệu một sự kết hợp chặt chẽ giữa việc triển khai áp dụng của phép nối bán phần và phần trên cùng. Các trường hợp đặc biệt và khớp nối chặt chẽ là những cách tuyệt vời để đưa ra lỗi và thực hiện các thay đổi trong tương lai khó khăn hơn và dễ xảy ra lỗi hơn.
- Trên cùng (1) sẽ dư thừa về mặt logic và chỉ hiển thị vì tác dụng phụ của mục tiêu hàng.
Điểm cuối cùng đáng được mở rộng với một ví dụ:
CHỌN P.ProductID TỪ SẢN XUẤT. SẢN PHẨM NHƯ PWHERE TỒN TẠI (CHỌN ĐẦU (1) TH.ProductID TỪ Sản xuất.TransactionHistory AS TH WHERE TH.ProductID =P.ProductID);
TOP (1)
trong truy vấn con tồn tại được đơn giản hóa bởi trình tối ưu hóa, đưa ra một kế hoạch thực thi bán nối đơn giản:
Trình tối ưu hóa cũng có thể loại bỏ DISTINCT
dư thừa hoặc GROUP BY
trong truy vấn con. Tất cả những điều sau đây đều tạo ra cùng một kế hoạch như trên:
- DISTINCTSELECT dự phòng P.ProductID TỪ SẢN XUẤT.Sản phẩm NHƯ PWHERE TỒN TẠI (CHỌN DISTINCT TH.ProductID TỪ Sản xuất.TransactionHistory AS TH WHERE TH.ProductID =P.ProductID); - NHÓM dự phòng BYSELECT P.ProductID FROM Production.Product AS PWHERE TỒN TẠI (CHỌN TH.ProductID TỪ Production.TransactionHistory AS TH WHERE TH.ProductID =P.ProductID GROUP BY TH.ProductID); - DISTINCT TOP dự phòng (1) CHỌN P.ProductID TỪ SẢN XUẤT. SẢN PHẨM NHƯ PWHERE TỒN TẠI (CHỌN DISTINCT TOP (1) TH.ProductID TỪ SẢN XUẤT.TransactionHistory AS TH WHERE TH.ProductID =P.ProductID);
Tóm tắt và Kết luận
Chỉ áp dụng kết nối bán vòng lặp lồng nhau có thể có mục tiêu hàng do trình tối ưu hóa đặt. Đây là kiểu kết hợp duy nhất đẩy (các) vị từ kết hợp xuống khỏi kết hợp, cho phép kiểm tra sự tồn tại của kết hợp được thực hiện sớm . Tham gia bán vòng lặp lồng nhau không liên quan hầu như không bao giờ * đặt mục tiêu hàng và bán băm hoặc hợp nhất cũng không tham gia. Áp dụng các vòng lặp lồng nhau có thể được phân biệt với tham gia các vòng lặp lồng nhau không có liên quan bởi sự hiện diện của tham chiếu bên ngoài (thay vì một vị từ) trên toán tử tham gia vòng lặp lồng nhau để áp dụng.
Cơ hội thấy một tham gia bán áp dụng trong kế hoạch thực hiện cuối cùng phần nào phụ thuộc vào hoạt động tối ưu hóa sớm. Thiếu cú pháp T-SQL trực tiếp, chúng ta phải diễn đạt các phép nối bán phần bằng các thuật ngữ gián tiếp. Chúng được phân tích cú pháp thành một cây logic có chứa một truy vấn con, mà hoạt động của trình tối ưu hóa ban đầu sẽ chuyển đổi thành một áp dụng và sau đó thành một kết nối bán không liên quan nếu có thể.
Hoạt động đơn giản hóa này xác định xem một kết nối bán hợp lý có được trình bày cho trình tối ưu hóa dựa trên chi phí dưới dạng một kết nối bán áp dụng hay thông thường hay không. Khi được trình bày dưới dạng hợp lý áp dụng bán tham gia, CBO gần như chắc chắn tạo ra một kế hoạch thực thi cuối cùng có các vòng lặp lồng nhau áp dụng vật lý (và do đó, đặt mục tiêu hàng). Khi được giới thiệu với một liên kết bán không liên quan, CBO có thể xem xét chuyển đổi thành áp dụng (hoặc có thể không). Sự lựa chọn cuối cùng của phương án là một loạt các quyết định dựa trên chi phí như thường lệ.
Giống như tất cả các mục tiêu theo hàng, mục tiêu theo hàng bán nối có thể là một điều tốt hoặc xấu đối với hiệu suất. Biết rằng liên kết bán áp dụng đặt ra mục tiêu hàng ít nhất sẽ giúp mọi người nhận ra và giải quyết nguyên nhân nếu sự cố xảy ra. Giải pháp sẽ không phải lúc nào (hoặc thậm chí thường) là vô hiệu hóa các mục tiêu hàng cho truy vấn. Các cải tiến trong lập chỉ mục (và / hoặc truy vấn) thường có thể được thực hiện để cung cấp một cách hiệu quả để xác định hàng phù hợp đầu tiên.
Tôi sẽ đề cập đến việc tham gia anti semi trong một bài viết riêng, tiếp tục chuỗi mục tiêu hàng.
* Ngoại lệ là một bán kết nối các vòng lặp lồng nhau không có liên quan với nhau không có vị từ nối (một trường hợp không phổ biến). Điều này thực sự đặt mục tiêu hàng.