Saya punya dua meja
@T1 TABLE
(
Id INT,
Date DATETIME
)
@T2 TABLE
(
Id INT,
Date DATETIME
)
Tabel ini memiliki indeks non-clustered pada (Id, Tanggal)
Dan saya bergabung dengan tabel ini
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
WHERE
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Ini juga dapat ditulis sebagai
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
AND
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Pertanyaan saya adalah, manakah dari dua pertanyaan ini yang memberikan kinerja lebih baik dan mengapa? Atau apakah mereka setara?
Jawaban:
Performanya akan sama. Pengoptimal akan mengenali ini dan membuat rencana yang sama.
Di sisi lain saya tidak akan mengatakan mereka setara. Bentuk pertama dalam pertanyaan jauh lebih mudah dibaca dan secara umum diharapkan.
Sebagai contoh menggunakan beberapa tabel yang saya miliki Anda dapat melihat rencana eksekusi persis sama tidak peduli bagaimana saya menulis permintaan.
Anda harus dapat menentukan rencana kueri untuk tabel dan kumpulan data Anda sendiri sehingga Anda dapat melihat apa yang terjadi dalam situasi Anda.
Berikan rencana eksekusi ini
sumber
INNER JOIN
. Jika Anda memasukkanOUTER JOIN
maka mereka jelas tidak sama.Mereka identik secara semantik dan pengoptimal seharusnya tidak kesulitan mengenali fakta ini dan menghasilkan rencana yang identik.
Saya cenderung untuk menempatkan kondisi referensi kedua tabel di
ON
dan kondisi referensi hanya satu tabel di tabelWHERE
.Untuk
OUTER JOINS
memindahkan kondisi dapat mempengaruhi semantik.sumber
Dalam kasus sederhana, itu akan sama. Namun, saya telah melihat pertanyaan yang sangat kompleks dengan beberapa bergabung memiliki rencana yang sangat berbeda. Yang baru-baru ini saya kerjakan dimulai dengan sebuah tabel yang memiliki hampir 6 juta baris bergabung dengan sekitar 20 tabel yang berbeda. Hanya gabungan pertama ke tabel ini yang merupakan gabungan internal , semua yang lain merupakan gabungan luar. Filter di mana klausa parameter sesuatu seperti ini:
Filter ini digunakan kemudian dalam paket alih-alih sebelumnya. Ketika saya memindahkan kondisi ini ke gabung bagian dalam pertama, rencananya berubah secara dramatis ketika filter diterapkan sejak awal dalam rencana untuk membatasi set hasil dan CPU saya dan waktu yang berlalu turun sekitar 310%. Jadi, seperti banyak pertanyaan SQL Server, itu tergantung.
sumber
Secara umum, tempat Anda meletakkan filter membuat perbedaan.
Sementara Tom V mengatakan Pengoptimal akan mengenali bahwa kueri itu sama dan menghasilkan rencana yang sama, itu tidak selalu benar. Tergantung pada versi SQL yang Anda gunakan, seberapa kompleks kueri Anda, dan seberapa penting untuk keseluruhan kumpulan yang ditentukan oleh Pengoptimal.
Pengoptimal dapat memutuskan bahwa bagian dari kumpulan ini tidak layak menghabiskan cukup waktu untuk memungkinkannya menghasilkan rencana terbaik. Secara umum Anda akan mendapatkan kinerja yang lebih baik jika Anda meletakkan kondisi yang mengurangi jumlah data yang perlu dikerjakan dalam klausa ON alih-alih klausa WHERE (jika mungkin, karena melakukan ini dengan sambungan luar akan menghasilkan produk Cartesian .)
Ini sedikit lebih mudah untuk Pengembang SQL sesekali untuk melihat filter di klausa WHERE, tapi saya telah bekerja pada beberapa tabel besar di mana memiliki filter di klausa ON memangkas jam dari run time.
Jadi, jika klausa memiliki potensi untuk secara drastis mengurangi jumlah baris kueri akan dibaca, saya akan selalu memasukkannya dalam klausa ON untuk membantu Pengoptimal memilih rencana yang lebih baik.
sumber
Dalam keadaan biasa, kondisi filter dapat ditentukan dalam klausa WHERE atau JOIN. Saya cenderung menempatkan filter di bawah DI MANA kecuali jika prioritas OUTER JOIN dapat terpengaruh (lihat di bawah) atau jika filter tersebut sangat spesifik untuk tabel itu (mis. TYPE = 12 untuk menentukan subset spesifik dari baris dalam tabel).
Di sisi lain, klausa ON dan WHERE dapat digunakan untuk menentukan kondisi gabungan (sebagai lawan dari kondisi filter). Selama Anda hanya menggunakan INNER bergabung, itu masih tidak masalah yang Anda gunakan dalam keadaan biasa.
Jika Anda menggunakan OUTER bergabung, bagaimanapun, itu bisa membuat banyak perbedaan. Jika, misalnya, Anda menentukan GABUNGAN LUAR antara dua tabel (t1 dan t2) tetapi kemudian, dalam klausa WHERE, lanjutkan untuk menentukan hubungan eqijoin antara tabel (misalnya t1.col = t2.col), Anda baru saja dikonversi menjadi OUTER join menjadi INNER join! Ini karena WHERE dapat digunakan untuk menentukan equijoin (atau mungkin bahkan OUTER bergabung, tergantung pada versinya, menggunakan sintaks yang sudah usang * =) tanpa menggunakan klausa ON, dan ketika WHERE menunjukkan equijoin bagian dalam di antara tabel, itu menimpa OUTER GABUNG (jika ada).
Pertanyaan aslinya adalah tentang filter, di mana jenis gabung sering kali tidak boleh menjadi masalah, tetapi gabung juga dapat bertindak sebagai filter dan dalam situasi tersebut penempatan kondisi gabung tentu saja bisa berarti.
sumber
Dengan INNER JOINs, ini adalah masalah gaya.
Namun, itu menjadi jauh lebih menarik dengan GABUNGAN LUAR. Anda harus menjelajahi perbedaan antara kueri dengan GABUNGAN LUAR dan kondisi di kedua klausa ON dan klausa WHERE. Hasil-set tidak selalu sama. Apakah, misalnya,
sama seperti
sumber