Pertanyaan Cara untuk menghindari operasi spool yang bersemangat di SQL Server


Saya memiliki proses ETL yang melibatkan prosedur tersimpan yang membuat penggunaan berat SELECT INTO pernyataan (minimal dicatat dan karena itu lebih cepat karena menghasilkan lebih sedikit lalu lintas log). Dari kumpulan pekerjaan yang terjadi dalam satu disimpan tertentu prosedur yang tersimpan beberapa operasi yang paling mahal adalah spool bersemangat yang tampaknya hanya buffer hasil query dan kemudian menyalinnya ke dalam tabel yang sedang dibuat.

Dokumentasi MSDN pada spool yang bersemangat cukup jarang. Adakah yang memiliki wawasan lebih dalam tentang apakah ini benar-benar diperlukan (dan dalam keadaan apa)? Saya memiliki beberapa teori yang mungkin atau mungkin tidak masuk akal, tetapi tidak berhasil menghilangkannya dari pertanyaan.

File .sqlplan cukup besar (160kb) jadi saya kira itu mungkin tidak masuk akal untuk mempostingnya langsung ke forum.

Jadi, inilah beberapa teori yang mungkin bisa menerima jawaban spesifik:

  • Kueri menggunakan beberapa UDF untuk transformasi data, seperti penguraian tanggal yang diformat. Apakah transformasi data ini mengharuskan penggunaan spul bersemangat untuk mengalokasikan jenis yang masuk akal (misalnya varchar length) ke tabel sebelum membuatnya?
  • Sebagai perpanjangan dari pertanyaan di atas, apakah ada yang memiliki pandangan yang lebih dalam tentang apa atau tidak mendorong operasi ini dalam sebuah query?

32
2017-09-17 20:23


asal


Jawaban:


Pemahaman saya tentang spooling adalah bahwa itu adalah sedikit herring merah pada rencana eksekusi Anda. Ya, itu menyumbang banyak biaya kueri Anda, tetapi sebenarnya ini adalah pengoptimalan yang dilakukan SQL Server secara otomatis sehingga dapat menghindari penyelematan biaya. Jika Anda menghindari spooling, biaya pohon eksekusi yang akan naik dan hampir pasti biaya seluruh permintaan akan meningkat. Saya tidak memiliki wawasan khusus apa yang secara khusus dapat menyebabkan pengoptimal kueri basis data mengurai eksekusi seperti itu, terutama tanpa melihat kode SQL, tetapi Anda mungkin lebih baik memercayai perilakunya.

Namun, itu tidak berarti rencana eksekusi Anda tidak dapat dioptimalkan, tergantung pada apa yang Anda lakukan dan seberapa bergejolaknya data sumber Anda. Ketika Anda melakukan SELECT INTOAnda akan sering melihat spooling item pada rencana eksekusi Anda, dan itu bisa terkait dengan membaca isolasi. Jika sesuai untuk situasi khusus Anda, Anda dapat mencoba menurunkan tingkat isolasi transaksi menjadi sesuatu yang lebih murah, dan / atau menggunakan NOLOCK petunjuk. Saya telah menemukan di pertanyaan performa-kritis yang rumit itu NOLOCK, jika aman dan sesuai untuk data Anda, dapat sangat meningkatkan kecepatan eksekusi kueri bahkan ketika tampaknya tidak ada alasan yang seharusnya.

Dalam situasi ini, jika Anda mencoba READ UNCOMMITTED atau NOLOCK petunjuk, Anda mungkin dapat menghilangkan beberapa Kumparan. (Tentunya Anda tidak ingin melakukan ini jika kemungkinan Anda akan mendarat dalam keadaan yang tidak konsisten, tetapi persyaratan isolasi data setiap orang berbeda). Itu TOP operator dan OR operator kadang-kadang dapat menyebabkan spooling, tapi saya ragu Anda melakukan salah satu dari mereka dalam proses ETL ...

Anda benar mengatakan bahwa UDF Anda juga bisa menjadi pelakunya. Jika Anda hanya menggunakan masing-masing UDF sekali, itu akan menjadi eksperimen yang menarik untuk mencoba menempatkan mereka secara inline untuk melihat apakah Anda mendapatkan manfaat kinerja yang besar. (Dan jika Anda tidak dapat menemukan cara untuk menulisnya sesuai dengan kueri, itu mungkin mengapa mereka mungkin menyebabkan spooling).

Satu hal terakhir yang saya lihat adalah, jika Anda melakukan gabungan apa pun yang dapat diurutkan ulang, coba gunakan petunjuk untuk memaksa agar perintah bergabung terjadi dalam apa yang Anda ketahui sebagai pesanan paling selektif. Itu sedikit jangkauan tetapi tidak ada salahnya untuk mencobanya jika Anda sudah terjebak mengoptimalkan.


26