Ini sama sekali bukan jawaban kanonik tapi saya perhatikan bahwa untuk rencana kueri nested loop yang ditunjukkan dalam SQL Fiddle dimungkinkan untuk menerapkan rencana dari Query 2 ke Query 1 dengan menggunakan USE PLAN
petunjuk tetapi mencoba operasi sebaliknya gagal dengan
Prosesor kueri tidak dapat menghasilkan rencana kueri karena petunjuk USE PLAN berisi rencana yang tidak dapat diverifikasi sebagai sah untuk kueri. Hapus atau ganti petunjuk USE PLAN. Untuk kemungkinan terbaik dari memaksa rencana berhasil, verifikasi bahwa rencana yang disediakan dalam petunjuk USE PLAN adalah yang dihasilkan secara otomatis oleh SQL Server untuk permintaan yang sama.
Menonaktifkan aturan transformasi pengoptimal ReorderLOJN
mencegah petunjuk rencana sukses sebelumnya juga berhasil.
Bereksperimen dengan jumlah yang lebih besar dari acara data yang SQL Server tentu mampu mengubah (A LOJ B) LOJ C
ke A LOJ (B LOJ C)
alami juga tapi aku tidak melihat bukti bahwa sebaliknya adalah benar.
Kasus yang sangat dibuat-buat di mana kueri pertama berkinerja lebih baik daripada yang kedua
DROP TABLE MyGrandChild , MyChild, MyParent
CREATE TABLE MyParent
(Id int)
CREATE TABLE MyChild
(Id int PRIMARY KEY
,ParentId int,
Filler char(8000) NULL)
CREATE TABLE MyGrandChild
(Id int
,ParentId int)
INSERT INTO MyChild
(Id, ParentId)
SELECT TOP (100000) ROW_NUMBER() OVER (ORDER BY @@SPID),
ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values v1, master..spt_values
INSERT INTO MyGrandChild
(Id, ParentId)
OUTPUT INSERTED.Id INTO MyParent
SELECT TOP (3000) Id, Id AS ParentId
FROM MyChild
ORDER BY Id
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SELECT gc.Id AS gcId,
gc.ParentId AS gcpId,
c.Id AS cId,
c.ParentId AS cpId,
p.Id AS pId
FROM MyGrandChild AS gc
LEFT OUTER JOIN MyChild AS c
ON c.[Id] = gc.[ParentId]
LEFT OUTER JOIN MyParent AS p
ON p.[Id] = c.[ParentId]
SELECT gc.Id AS gcId,
gc.ParentId AS gcpId,
c.Id AS cId,
c.ParentId AS cpId,
p.Id AS pId
FROM MyGrandChild AS gc
LEFT OUTER JOIN( MyChild AS c
LEFT OUTER JOIN MyParent AS p
ON p.[Id] = c.[ParentId])
ON c.[Id] = gc.[ParentId]
Yang memberi rencana
Bagi saya, Kueri 1 memiliki waktu yang telah berlalu 108 ms vs 1.163 ms untuk Kueri 2.
Pertanyaan 1
Table 'Worktable'. Scan count 0, logical reads 0
Table 'MyChild'. Scan count 0, logical reads 9196
Table 'MyGrandChild'. Scan count 1, logical reads 7
Table 'MyParent'. Scan count 1, logical reads 5
Pertanyaan 2
Table 'MyParent'. Scan count 1, logical reads 15000
Table 'MyChild'. Scan count 0, logical reads 9000
Table 'MyGrandChild'. Scan count 1, logical reads 7
Jadi mungkin untuk sementara diasumsikan bahwa sintaks pertama ("tidak dicoba") berpotensi menguntungkan karena memungkinkan lebih banyak pesanan bergabung yang potensial untuk dipertimbangkan, tetapi saya belum melakukan pengujian yang cukup mendalam untuk memiliki banyak kepercayaan dalam hal ini sebagai aturan umum.
Sangat mungkin untuk memberikan contoh tandingan di mana Kueri 2 berkinerja lebih baik. Coba keduanya dan lihat rencana eksekusi.