Saya punya query SQL Server 2008 yang agak rumit (sekitar 200 baris SQL yang cukup padat) yang tidak berfungsi seperti yang saya butuhkan. Seiring waktu, kinerja turun dari sekitar 0,5 detik menjadi sekitar 2 detik.
Melihat rencana pelaksanaannya, cukup jelas bahwa dengan menyusun kembali sambungan, kinerja dapat ditingkatkan. Ya, dan itu ... turun menjadi sekitar, 3 detik. Sekarang kueri memiliki petunjuk "OPSI FORCE ORDER" , dan hidup itu baik.
Datanglah saya hari ini, membersihkan database. Saya mengarsipkan sekitar 20% dari baris, tidak mengambil tindakan dalam database yang relevan kecuali menghapus baris ... rencana eksekusi akan BENAR-BENAR disemprot . Ini sepenuhnya salah menilai berapa banyak baris yang akan dikembalikan oleh sub-sub-sub, dan (misalnya) menggantikan:
<Hash>
dengan
<NestedLoops Optimized='false' WithUnorderedPrefetch='true'>
Sekarang waktu kueri melonjak dari sekitar 0,3 detik menjadi sekitar 18 detik. (!) Hanya karena saya menghapus baris. Jika saya menghapus petunjuk permintaan saya kembali ke waktu permintaan 2s. Lebih baik, tapi lebih buruk.
Saya telah mereproduksi masalah setelah memulihkan database ke beberapa lokasi dan server. Cukup menghapus sekitar 20% baris dari setiap tabel selalu menyebabkan masalah ini.
- Apakah ini normal untuk pesanan gabungan paksa untuk membuat perkiraan kueri menjadi benar-benar tidak akurat (dan karenanya waktu kueri tidak dapat diprediksi)?
- Haruskah saya berharap bahwa saya harus menerima kinerja kueri yang kurang optimal, atau menontonnya seperti elang dan sering mengedit petunjuk kueri secara manual? Atau mungkin mengisyaratkan setiap bergabung juga? 3s ke 2s adalah hit besar untuk diambil.
- Apakah jelas mengapa pengoptimal meledak setelah menghapus baris? Misalnya, "ya, diperlukan pemindaian sampel, dan karena saya mengarsipkan sebagian besar baris sebelumnya dalam riwayat data sampel menghasilkan hasil yang jarang, sehingga meremehkan kebutuhan untuk operasi hash yang diurutkan"?
Jika Anda ingin melihat rencana eksekusi, harap sarankan lokasi yang dapat saya posting. Kalau tidak, saya sudah mencicipi sedikit yang paling menakjubkan. Inilah perkiraan salah yang mendasar, angka dalam paren adalah baris (perkiraan: aktual).
/ Clustered Index Scan (908:7229)
Nested Loops (Inner Join) --<
\ NonClustered Index Seek (1:7229)
Perhatikan bahwa loop dalam diharapkan untuk memindai 908 baris, tetapi sebaliknya memindai 52.258.441. Jika sudah akurat, cabang ini akan berlari sekitar 2ms, bukan 12detik. Sebelum menghapus baris, estimasi gabungan dalam ini hanya dimatikan oleh faktor total 2, dan dilakukan sebagai pencocokan hash pada dua indeks berkerumun.