Tại sao thay đổi thứ tự cột tham gia khai báo giới thiệu một loại?


40

Tôi có hai bảng với các cột chính được đặt tên, đánh máy và được lập chỉ mục. Một trong số chúng có một chỉ mục cụm duy nhất , một cái khác có một không duy nhất .

Cài đặt thử nghiệm

Tập lệnh thiết lập, bao gồm một số thống kê thực tế:

DROP TABLE IF EXISTS #left;
DROP TABLE IF EXISTS #right;

CREATE TABLE #left (
    a       char(4) NOT NULL,
    b       char(2) NOT NULL,
    c       varchar(13) NOT NULL,
    d       bit NOT NULL,
    e       char(4) NOT NULL,
    f       char(25) NULL,
    g       char(25) NOT NULL,
    h       char(25) NULL
    --- and a few other columns
);

CREATE UNIQUE CLUSTERED INDEX IX ON #left (a, b, c, d, e, f, g, h)

UPDATE STATISTICS #left WITH ROWCOUNT=63800000, PAGECOUNT=186000;

CREATE TABLE #right (
    a       char(4) NOT NULL,
    b       char(2) NOT NULL,
    c       varchar(13) NOT NULL,
    d       bit NOT NULL,
    e       char(4) NOT NULL,
    f       char(25) NULL,
    g       char(25) NOT NULL,
    h       char(25) NULL
    --- and a few other columns
);

CREATE CLUSTERED INDEX IX ON #right (a, b, c, d, e, f, g, h)

UPDATE STATISTICS #right WITH ROWCOUNT=55700000, PAGECOUNT=128000;

Lời trách móc

Khi tôi tham gia hai bảng này trên các khóa phân cụm của chúng, tôi mong đợi một tham gia MERGE một-nhiều, như vậy:

SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
    l.a=r.a AND
    l.b=r.b AND
    l.c=r.c AND
    l.d=r.d AND
    l.e=r.e AND
    l.f=r.f AND
    l.g=r.g AND
    l.h=r.h
WHERE l.a='2018';

Đây là kế hoạch truy vấn tôi muốn:

Đây là những gì tôi muốn.

(Đừng bận tâm đến các cảnh báo, họ phải làm với các số liệu thống kê giả mạo.)

Tuy nhiên, nếu tôi thay đổi thứ tự của các cột xung quanh trong phép nối, như vậy:

SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
    l.c=r.c AND     -- used to be third
    l.a=r.a AND     -- used to be first
    l.b=r.b AND     -- used to be second
    l.d=r.d AND
    l.e=r.e AND
    l.f=r.f AND
    l.g=r.g AND
    l.h=r.h
WHERE l.a='2018';

... điều này xảy ra:

Kế hoạch truy vấn sau khi thay đổi thứ tự cột được khai báo trong phép nối.

Toán tử Sắp xếp dường như sắp xếp các luồng theo thứ tự khai báo của phép nối, nghĩa là c, a, b, d, e, f, g, hthêm thao tác chặn vào kế hoạch truy vấn của tôi.

Những điều tôi đã xem

  • Tôi đã thử thay đổi các cột thành NOT NULL, kết quả tương tự.
  • Bảng ban đầu được tạo với ANSI_PADDING OFF, nhưng việc tạo bảng ANSI_PADDING ONkhông ảnh hưởng đến kế hoạch này.
  • Tôi đã thử một INNER JOINthay vì LEFT JOIN, không thay đổi.
  • Tôi đã phát hiện ra nó trên Doanh nghiệp 2014 SP2, đã tạo một bản repro trên Nhà phát triển 2017 (CU hiện tại).
  • Xóa mệnh đề WHERE trên cột chỉ mục hàng đầu sẽ tạo ra kế hoạch tốt, nhưng nó ảnh hưởng đến kết quả .. :)

Cuối cùng, chúng ta đến câu hỏi

  • Đây có phải là cố ý?
  • Tôi có thể loại bỏ sắp xếp mà không thay đổi truy vấn (đó là mã nhà cung cấp, vì vậy tôi thực sự không muốn ...). Tôi có thể thay đổi bảng và chỉ mục.

Câu trả lời:


28

Đây có phải là cố ý?

Đó là theo thiết kế, vâng. Nguồn công khai tốt nhất cho xác nhận này đã không may bị mất khi Microsoft rút trang web phản hồi Connect, xóa sạch nhiều nhận xét hữu ích từ các nhà phát triển trong nhóm SQL Server.

Dù sao, thiết kế tối ưu hóa hiện tại không chủ động tìm cách tránh các loại không cần thiết mỗi se . Điều này thường gặp nhất với các chức năng cửa sổ và tương tự, nhưng cũng có thể được nhìn thấy với các toán tử khác nhạy cảm với việc đặt hàng, và đặc biệt là bảo toàn thứ tự giữa các toán tử.

Tuy nhiên, trình tối ưu hóa khá tốt (trong nhiều trường hợp) trong việc tránh sắp xếp không cần thiết, nhưng kết quả này thường xảy ra vì những lý do khác hơn là tích cực thử các kết hợp đặt hàng khác nhau. Theo nghĩa đó, không có quá nhiều câu hỏi về 'không gian tìm kiếm' vì đây là sự tương tác phức tạp giữa các tính năng tối ưu hóa trực giao đã được chứng minh là làm tăng chất lượng kế hoạch chung với chi phí chấp nhận được.

Ví dụ, việc sắp xếp thường có thể tránh được chỉ bằng cách khớp một yêu cầu đặt hàng (ví dụ: cấp cao nhất ORDER BY) với một chỉ mục hiện có. Trong trường hợp của bạn có thể có nghĩa là thêm ORDER BY l.a, l.b, l.c, l.d, l.e, l.f, l.g, l.h;nhưng đây là một sự đơn giản hóa quá mức (và không thể chấp nhận được vì bạn không muốn thay đổi truy vấn).

Tổng quát hơn, mỗi nhóm ghi nhớ có thể được liên kết với các thuộc tính bắt buộc hoặc mong muốn, có thể bao gồm thứ tự đầu vào. Khi không có lý do rõ ràng để thực thi một đơn đặt hàng cụ thể (ví dụ để đáp ứng ORDER BYhoặc để đảm bảo kết quả chính xác từ một nhà điều hành vật lý nhạy cảm với đơn hàng), có một yếu tố 'may mắn' liên quan. Tôi đã viết thêm về các chi tiết cụ thể khi nó liên quan đến việc hợp nhất tham gia (trong chế độ kết hợp hoặc tham gia) trong Tránh Sắp xếp với Hợp nhất Tham gia Ghép nối . Phần lớn trong số đó vượt ra ngoài diện tích bề mặt được hỗ trợ của sản phẩm, vì vậy hãy coi nó là thông tin và có thể thay đổi.

Trong trường hợp cụ thể của bạn, có, bạn có thể điều chỉnh việc lập chỉ mục như jadarnel27 gợi ý để tránh các loại; mặc dù có rất ít lý do để thực sự thích hợp nhất tham gia ở đây. Bạn cũng có thể gợi ý lựa chọn giữa băm hoặc tham gia vật lý vòng lặp bằng OPTION(HASH JOIN, LOOP JOIN)cách sử dụng Hướng dẫn kế hoạch mà không thay đổi truy vấn, tùy thuộc vào kiến ​​thức của bạn về dữ liệu và sự đánh đổi giữa hiệu suất tốt nhất, tồi tệ nhất và trường hợp trung bình.

Cuối cùng, vì tò mò, lưu ý rằng các loại có thể tránh được một cách đơn giản ORDER BY l.b, với chi phí của một sự hợp nhất nhiều-nhiều-ít có hiệu quả tham gia bmột mình, với phần dư phức tạp. Tôi đề cập đến điều này chủ yếu như một minh họa về sự tương tác giữa các tính năng tối ưu hóa mà tôi đã đề cập trước đây và cách các yêu cầu cấp cao nhất có thể truyền bá.


19

Tôi có thể loại bỏ sắp xếp mà không thay đổi truy vấn (đó là mã nhà cung cấp, vì vậy tôi thực sự không muốn ...). Tôi có thể thay đổi bảng và chỉ mục.

Nếu bạn có thể thay đổi các chỉ mục, thì việc thay đổi thứ tự của chỉ mục trên #rightđể khớp với thứ tự của các bộ lọc trong phép nối sẽ loại bỏ sắp xếp (đối với tôi):

CREATE CLUSTERED INDEX IX ON #right (c, a, b, d, e, f, g, h)

Đáng ngạc nhiên (ít nhất là với tôi), điều này dẫn đến kết quả là không có truy vấn nào kết thúc bằng một loại.

Đây có phải là cố ý?

Nhìn vào đầu ra từ một số cờ theo dõi kỳ lạ , có một sự khác biệt thú vị trong cấu trúc Ghi nhớ cuối cùng:

ảnh chụp màn hình của cấu trúc ghi nhớ cuối cùng cho mỗi truy vấn

Như bạn có thể thấy trong "Nhóm gốc" ở trên cùng, cả hai truy vấn đều có tùy chọn sử dụng Hợp nhất tham gia làm hoạt động vật lý chính để thực hiện truy vấn này.

Truy vấn tốt

Việc nối mà không có sắp xếp được điều khiển bởi nhóm 29 tùy chọn 1 và nhóm 31 tùy chọn 1 (mỗi trong số đó là quét phạm vi trên các chỉ mục liên quan). Nó được lọc bởi nhóm 27 (không hiển thị), đây là chuỗi các hoạt động so sánh logic giúp lọc tham gia.

Truy vấn xấu

Nhóm sắp xếp được điều khiển bởi các tùy chọn (mới) 3 mà mỗi trong hai nhóm đó (29 và 31) có. Tùy chọn 3 thực hiện sắp xếp vật lý trên kết quả của các lần quét phạm vi được đề cập trước đó (tùy chọn 1 của mỗi nhóm đó).

Tại sao?

Vì một số lý do, tùy chọn sử dụng trực tiếp 29.1 và 31.1 làm nguồn cho phép nối hợp nhất thậm chí không có sẵn cho trình tối ưu hóa trong truy vấn thứ hai. Mặt khác, tôi nghĩ rằng nó sẽ được liệt kê dưới nhóm gốc trong số các tùy chọn khác. Nếu nó có sẵn ở tất cả, thì nó chắc chắn sẽ chọn những người trong các hoạt động sắp xếp đắt tiền hơn.

Tôi chỉ có thể kết luận rằng:

  • đây là một lỗi (hoặc nhiều khả năng là một hạn chế) trong thuật toán tìm kiếm của trình tối ưu hóa
    • việc thay đổi các chỉ mục và tham gia chỉ có 5 phím sẽ loại bỏ sắp xếp cho truy vấn thứ hai (tất cả các phím 6, 7 và 8 đều có sắp xếp).
    • Điều này ngụ ý rằng không gian tìm kiếm có 8 khóa lớn đến mức trình tối ưu hóa không có thời gian để xác định giải pháp không sắp xếp là một tùy chọn khả thi trước khi nó kết thúc sớm với lý do "tìm thấy kế hoạch đủ tốt"
    • Đối với tôi có vẻ hơi khó hiểu rằng thứ tự của các điều kiện tham gia ảnh hưởng đến quá trình tìm kiếm của trình tối ưu hóa rất nhiều, nhưng thực sự điều đó hơi quá đầu tôi
  • sắp xếp là cần thiết để đảm bảo tính chính xác trong kết quả
    • điều này dường như không thể xảy ra, vì truy vấn có thể chạy mà không cần sắp xếp khi có ít khóa hơn hoặc các khóa được chỉ định theo một thứ tự khác

Hy vọng rằng ai đó có thể đi cùng và giải thích lý do tại sao yêu cầu sắp xếp, nhưng tôi nghĩ rằng sự khác biệt trong tòa nhà Ghi nhớ là đủ thú vị để đăng dưới dạng câu trả lời.


1
Tôi tin rằng nhận xét của bạn về không gian tìm kiếm thực sự là trường hợp ở đây. để chỉ sử dụng các chỉ mục, trình tối ưu hóa phải xác minh chúng đủ cho các điều kiện, qua 5 phím có quá nhiều khả năng để kiểm tra trước khi phải quay lại. Tôi tò mò, nếu tất cả các kết hợp thứ tự của truy vấn được liệt kê, có bao nhiêu trình tối ưu hóa sẽ thành công trong việc chống lại
Mr.Mindor

Và vâng, sự không nhất quán có vẻ hơi lỗi, nhưng có lẽ hoàn toàn phụ thuộc vào thuật toán được sử dụng để xác minh các chỉ mục là đủ. Nếu tất cả các kết hợp đã được thử nghiệm, có lẽ bạn sẽ có thể thấy mẫu trong kết quả và xác định thuật toán nào được sử dụng. Tôi cá là nó được viết để thực hiện tối ưu cho các trường hợp sử dụng điển hình hơn. Một giải pháp thay thế có thể tồn tại có thể tìm thấy giải pháp 8 phím đáng tin cậy trong thời gian giới hạn, nhưng nó chậm hơn giải pháp hiện tại khi có ít hơn 3-4 phím.
Mr.Mindor
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.