Untuk kueri yang cukup rumit yang saya coba optimalkan, saya perhatikan bahwa menghapus TOP n
klausa mengubah rencana eksekusi. Saya akan menduga bahwa ketika sebuah kueri memasukkan TOP n
mesin basis data akan menjalankan kueri mengabaikan TOP
klausa, dan kemudian pada akhirnya hanya mengecilkan hasil yang ditetapkan ke n jumlah baris yang diminta. Rencana eksekusi grafis tampaknya mengindikasikan hal ini - TOP
adalah langkah "terakhir". Tetapi tampaknya ada lebih banyak hal yang terjadi.
Pertanyaan saya adalah, bagaimana (dan mengapa) klausa TOP n berdampak pada rencana eksekusi permintaan?
Berikut ini adalah versi sederhana dari apa yang terjadi dalam kasus saya:
Kueri mencocokkan baris dari dua tabel, A dan B.
Tanpa TOP
klausa, pengoptimal memperkirakan akan ada 19k baris dari tabel A dan 46k baris dari tabel B. Jumlah aktual baris yang dikembalikan adalah 16k untuk A dan 13k untuk B. Kecocokan hash digunakan untuk menggabungkan dua set hasil ini untuk total 69 baris (kemudian diterapkan semacam). Permintaan ini terjadi dengan sangat cepat.
Ketika saya menambahkan TOP 1001
pengoptimal tidak menggunakan kecocokan hash; sebagai gantinya ia mengurutkan hasil dari tabel A (estimasi yang sama / aktual 19k / 16k) dan melakukan loop bersarang terhadap tabel B. Perkiraan jumlah baris untuk tabel B sekarang 1, dan yang aneh adalah bahwa TOP n
secara langsung mempengaruhi perkiraan jumlah eksekusi (pencarian indeks) terhadap B - sepertinya selalu 2n +1 , atau dalam kasus saya 2003. Estimasi ini berubah sesuai jika saya berubah TOP n
. Tentu saja, karena ini adalah nested join, jumlah aktual eksekusi adalah 16rb (jumlah baris dari tabel A) dan ini memperlambat query.
Skenario aktual sedikit lebih rumit tetapi ini menangkap ide dasar / perilaku. Kedua tabel dicari menggunakan indeks pencarian. Ini adalah edisi SQL Server 2008 R2 Enterprise.
ORDER BY
klausa. MenambahkanTOP
perubahan di mana dalam rencana semacam ini terjadi, tapi saya lebih khawatir tentang bagaimana hal itu mempengaruhi jumlah eksekusi indeks yang dicari terhadap tabel B ... (tentu saja keduanya mungkin terkait - saya tidak tahu)FAST num_rows
petunjuk kueri.Jawaban:
Cara di atas diungkapkan membuat saya berpikir Anda mungkin memiliki gambaran mental yang salah tentang bagaimana sebuah query dieksekusi. Operator dalam rencana kueri bukan langkah (di mana set hasil lengkap dari langkah sebelumnya dievaluasi oleh yang berikutnya.
SQL Server menggunakan model eksekusi pipelined , di mana setiap operator memperlihatkan metode seperti Init () , GetRow () , dan Close () . Seperti yang ditunjukkan oleh nama GetRow () , operator menghasilkan satu baris pada saat dibutuhkan (seperti yang disyaratkan oleh operator induknya). Ini didokumentasikan dalam referensi Buku Logistik Online dan Operator Fisik , dengan lebih detail di posting blog saya Mengapa Rencana Kueri Jalankan Mundur . Model baris per waktu ini sangat penting dalam membentuk intuisi suara untuk eksekusi permintaan.
Beberapa operasi logis seperti
TOP
, semi gabung danFAST n
petunjuk kueri memengaruhi cara pengoptimal biaya menentukan alternatif rencana eksekusi. Ide dasarnya adalah bahwa satu bentuk rencana yang mungkin dapat mengembalikan n baris pertama lebih cepat daripada rencana lain yang dioptimalkan untuk mengembalikan semua baris.Misalnya, loop bersarang yang diindeks bergabung seringkali merupakan cara tercepat untuk mengembalikan sejumlah kecil baris, meskipun hash atau gabungan penggabungan dengan pemindaian mungkin lebih efisien pada set yang lebih besar. Cara pengoptimal kueri alasan tentang pilihan-pilihan ini adalah dengan menetapkan Tujuan Baris pada titik tertentu di pohon logis operasi.
Sasaran baris memodifikasi cara alternatif rencana kueri dihitung biayanya. Inti dari itu adalah bahwa pengoptimal dimulai dengan menghitung biaya setiap operator seolah-olah set hasil penuh diperlukan, menetapkan tujuan baris pada titik yang sesuai, dan kemudian bekerja kembali ke pohon rencana memperkirakan jumlah baris yang diharapkan perlu untuk memeriksa untuk memenuhi tujuan baris.
Misalnya, logis
TOP(10)
menetapkan sasaran baris 10 pada titik tertentu di pohon kueri logis. Biaya operator yang mengarah ke sasaran baris dimodifikasi untuk memperkirakan berapa banyak baris yang harus mereka hasilkan untuk memenuhi sasaran baris. Perhitungan ini bisa menjadi rumit, sehingga lebih mudah untuk memahami semua ini dengan contoh yang berfungsi penuh dan rencana eksekusi beranotasi. Sasaran baris dapat memengaruhi lebih dari pilihan jenis gabungan atau apakah pencarian dan pencarian lebih disukai daripada pemindaian. Lebih detail tentang itu di sini .Seperti biasa, rencana eksekusi yang dipilih berdasarkan sasaran baris tunduk pada kemampuan penalaran pengoptimal dan kualitas informasi yang diberikan kepadanya. Tidak setiap rencana dengan sasaran baris akan menghasilkan jumlah baris yang diperlukan lebih cepat dalam praktiknya, tetapi menurut model penetapan biaya akan melakukannya.
Jika rencana sasaran baris terbukti tidak lebih cepat, biasanya ada cara untuk mengubah kueri atau memberikan informasi yang lebih baik kepada pengoptimal sehingga rencana yang dipilih secara alami adalah yang terbaik. Pilihan mana yang sesuai dalam kasus Anda tergantung pada rinciannya. Fitur tujuan baris umumnya sangat efektif (meskipun ada bug yang harus diperhatikan ketika digunakan dalam rencana eksekusi paralel).
Permintaan dan rencana khusus Anda mungkin tidak cocok untuk analisis terperinci di sini (dengan segala cara sediakan rencana eksekusi aktual jika Anda mau), tetapi mudah-mudahan gagasan yang diuraikan di sini akan memungkinkan Anda untuk membuat kemajuan ke depan.
sumber
Ketika Anda menggunakan TOP, Pengoptimal melihat peluang untuk melakukan lebih sedikit pekerjaan. Jika Anda meminta 10 baris, maka ada peluang bagus tidak perlu menghabiskan seluruh rangkaian. Sehingga operator TOP dapat didorong lebih jauh ke kanan. Itu akan terus meminta baris dari operator berikutnya (di sebelah kanan), sampai cukup diterima.
Anda menunjukkan bahwa tanpa TOP, kueri mengurutkan data di bagian paling akhir. Jika mesin dapat mengetahui berapa banyak baris yang akan dipenuhi oleh sambungan terlebih dahulu, mungkin lebih baik menggunakan rencana yang sama, menempatkan posisi TOP di sebelah kiri. Tetapi dengan upaya untuk melakukan Pencocokan Hash menjadi relatif tinggi, dan mungkin tidak ada pilihan untuk Gabung Gabung, Pengoptimal mungkin lebih memilih untuk menyaring TOP lebih jauh ke kanan.
Ketika tabel B ditanya, itu mengambil satu baris sekaligus. Itu sebabnya perkiraannya adalah 1. Ia juga mengasumsikan bahwa hanya akan menemukan baris itu 50% dari waktu. Jadi tebakannya perlu 2n +1 berusaha untuk menemukannya.
sumber
TOP
klausa? Terima kasih atas jawaban / kesabaran Anda.