SQL Server Bergabung / tempat pemrosesan order

18

Setelah membaca permintaan SQL Lambat, tidak yakin bagaimana mengoptimalkan , itu membuat saya berpikir tentang kinerja umum permintaan. Tentunya, kita perlu hasil dari tabel pertama (ketika tabel lain bergabung) menjadi sekecil mungkin sebelum bergabung (bergabung dalam untuk pertanyaan ini) untuk membuat pertanyaan kami yang sedikit lebih cepat lebih cepat.

Contoh, jika ini:

SELECT *
FROM   ( SELECT * FROM table1 WHERE col = @val ) t
INNER JOIN table2 ON col = col2

Lebih baik / lebih cepat dari:

SELECT *
FROM table1
INNER JOIN table2 ON col = col2
WHERE table1.col = @val

Teori saya adalah sebagai berikut (ini mungkin bukan implementasi yang benar, saya mencoba mengingat dari buku internal SQL Server 2008 yang saya baca (MSFT Press)):

  1. Prosesor permintaan pertama mendapatkan tabel kiri (table1)
  2. Bergabung dengan tabel kedua (table2) dan bentuk produk kartesius sebelum menyaring baris yang diperlukan (jika ada)
  3. Kemudian lakukan klausa WHERE, ORDER BY, GROUP BY, HAVING dengan pernyataan SEELCT yang terakhir.

Jadi, jika dalam pernyataan # 1 di atas, tabel lebih kecil, mesin SQL memiliki lebih sedikit pekerjaan yang harus dilakukan ketika membentuk produk cartesian. Kemudian ketika Anda mencapai pernyataan di mana, Anda memiliki hasil yang berkurang yang digunakan untuk memfilter dalam memori.

Saya bisa jadi jauh dari sasaran itu tidak nyata. Seperti yang saya katakan, itu teori.

Pikiran Anda?

Catatan : Saya baru saja memikirkan pertanyaan ini dan belum sempat menjalankan tes sendiri.

Catatan 2 : Ditandai sebagai SQL Server karena saya tidak tahu apa - apa tentang implementasi MySql, dll. Silakan jawab / komentar saja

Stuart Blackler
sumber

Jawaban:

15

Pemrosesan logis kueri ada di MSDN (ditulis oleh tim Microsoft SQL Server, bukan pihak ke-3)

1. FROM
2. ON
3. JOIN
4. WHERE
5. GROUP BY
6. WITH CUBE or WITH ROLLUP
7. HAVING
8. SELECT
9. DISTINCT
10. ORDER BY
11. TOP

Tabel turunan mengikuti ini, lalu kueri luar melakukannya lagi, dll

Ini logis : tidak aktual . Tidak peduli bagaimana SQL Server benar-benar melakukannya, semantik ini dihormati untuk surat itu . "Aktual" ditentukan oleh Pengoptimal Kueri (QO) dan Anda menghindari produk Cartesion perantara yang Anda sebutkan.

Perlu disebutkan bahwa SQL adalah deklaratif: Anda mengatakan "apa" tidak "bagaimana" seperti yang Anda lakukan untuk pemrograman prosedural / imperatif (Java, .net). Jadi mengatakan "ini terjadi sebelum itu" salah dalam banyak kasus (mis. Asumsi hubung singkat atau perintah L-to-R WHERE)

Dalam kasus Anda di atas, QO akan menghasilkan rencana yang sama tidak peduli bagaimana terstruktur karena itu adalah permintaan sederhana.

Namun, QO berbasis biaya dan untuk permintaan yang kompleks mungkin diperlukan 2 minggu untuk menghasilkan rencana yang ideal. Jadi itu "cukup baik" yang sebenarnya tidak.

Jadi kasus pertama Anda dapat membantu pengoptimal menemukan rencana yang lebih baik karena urutan pemrosesan logis berbeda untuk 2 kueri. Tapi mungkin tidak.

Saya telah menggunakan trik ini pada SQL Server 2000 untuk mendapatkan peningkatan kinerja kecepatan 60x pada permintaan pelaporan. Ketika QO meningkatkan versi ke versi, menjadi lebih baik dalam mengerjakan hal-hal ini.

Dan buku yang Anda sebutkan: ada beberapa perselisihan tentang hal itu.
Lihat SO dan tautan selanjutnya: /programming//q/3270338/27535

gbn
sumber
6

Permintaan SQL tidak bersifat prosedural, tidak ada pemrosesan atas ke bawah dari operator yang bergabung. Pemesanan tabel dalam kueri contoh Anda tidak memiliki pengaruh pada rencana eksekusi karena mereka secara logis setara dan akan menghasilkan rencana yang persis sama.

Anda semacam mengevaluasi dua opsi yang mungkin dipertimbangkan pengoptimal kueri saat membuat rencana untuk kueri ini. Faktor utama yang memengaruhi pilihan rencana adalah statistik untuk tabel yang terlibat dan biaya yang terkait dengan pilihan operator dalam setiap rencana kandidat.

Penggabungan dua tabel yang sangat sederhana seperti contoh Anda dapat dipenuhi dengan salah satu dari ratusan rencana eksekusi yang berbeda. Pengoptimal memutuskan cara terbaik untuk menjawab pertanyaan Anda dengan membandingkan biaya paket ini.

Terkadang ada kesalahan dan Anda dapat membantunya membuat pilihan yang lebih baik melalui pengindeksan yang ditingkatkan, menjaga statistik diperbarui dan menerapkan petunjuk. Dalam kasus yang sangat jarang, Anda mungkin ingin memaksakan urutan eksekusi dengan menggunakan petunjuk FORCE ORDER tetapi itu harus digunakan dengan hemat. Ini adalah palu untuk memecahkan kacang, pengoptimal biasanya dapat digoda untuk menghasilkan rencana yang lebih baik dengan memberinya informasi yang lebih baik.

Mark Storey-Smith
sumber