Saya memiliki dua tabel dengan kolom kunci yang dinamai identik, diketik, dan diindeks. Salah satunya memiliki indeks berkerumun unik , yang lain memiliki non-unik .
Pengaturan tes
Skrip penyiapan, termasuk beberapa statistik realistis:
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;
Repro itu
Ketika saya bergabung dengan dua tabel ini pada kunci pengelompokan mereka, saya berharap satu-ke-banyak Gabung bergabung, seperti:
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';
Ini adalah paket permintaan yang saya inginkan:
(Jangankan peringatan, itu ada hubungannya dengan statistik palsu.)
Namun, jika saya mengubah urutan kolom di dalam gabungan, seperti:
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';
... ini terjadi:
Operator Sortir tampaknya memesan stream sesuai dengan urutan gabungan yang dinyatakan, yaitu c, a, b, d, e, f, g, h
, yang menambahkan operasi pemblokiran ke rencana kueri saya.
Hal-hal yang telah saya lihat
- Saya sudah mencoba mengubah kolom menjadi
NOT NULL
, hasil yang sama. - Tabel asli dibuat dengan
ANSI_PADDING OFF
, tetapi membuatnya denganANSI_PADDING ON
tidak memengaruhi rencana ini. - Saya mencoba
INNER JOIN
bukanLEFT JOIN
, tidak ada perubahan. - Saya menemukannya di Perusahaan SP2 2014, membuat repro pada Pengembang 2017 (CU saat ini).
- Menghapus klausa WHERE pada kolom indeks utama memang menghasilkan rencana yang baik, tetapi itu mempengaruhi hasil .. :)
Akhirnya, kita sampai pada pertanyaan
- Apakah ini disengaja?
- Dapatkah saya menghilangkan semacam itu tanpa mengubah kueri (yang merupakan kode vendor, jadi saya lebih suka tidak ...). Saya bisa mengubah tabel dan indeks.