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:
(Đừ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:
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, h
thê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ảngANSI_PADDING ON
không ảnh hưởng đến kế hoạch này. - Tôi đã thử một
INNER JOIN
thay 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.