Ada kueri di mana ketika kita menekan "mengeksekusi", ini menunjukkan beberapa baris dan terus bertambah, tetapi kueri belum berakhir. Namun terkadang, menunggu sampai akhir permintaan.
Mengapa ini terjadi? Apakah ada cara untuk mengendalikan ini?
Ada kueri di mana ketika kita menekan "mengeksekusi", ini menunjukkan beberapa baris dan terus bertambah, tetapi kueri belum berakhir. Namun terkadang, menunggu sampai akhir permintaan.
Mengapa ini terjadi? Apakah ada cara untuk mengendalikan ini?
Jawaban:
Jawabannya, seperti biasa (baik-baik saja, sebagian besar waktu), terletak pada rencana eksekusi.
Ada operator tertentu yang meminta semua baris untuk sampai pada mereka sebelum mereka dapat mulai memproses baris tersebut, dan meneruskannya ke hilir, misalnya:
Mereka disebut memblokir, atau menghentikan dan pergi karena itu, dan mereka sering dipilih ketika pengoptimal berpikir itu harus memproses banyak data untuk menemukan data Anda.
Ada operator lain yang dapat mulai streaming, atau melewati setiap baris yang ditemukan dengan segera
Ketika kueri mulai mengembalikan data dengan segera, tetapi tidak menyelesaikannya dengan segera, biasanya itu merupakan tanda bahwa pengoptimal memilih rencana untuk menemukan dan mengembalikan beberapa baris dengan cepat menggunakan operator yang memiliki biaya awal yang lebih rendah.
Ini dapat terjadi karena sasaran baris yang diperkenalkan oleh Anda, atau oleh pengoptimal.
Ini juga dapat terjadi jika rencana buruk dipilih karena beberapa alasan (kurangnya SARGability, parameter sniffing, statistik tidak mencukupi, dll.), Tetapi itu membutuhkan lebih banyak penggalian untuk mencari tahu.
Untuk informasi lebih lanjut, lihat blog Rob Farley di sini
Dan seri Paul White tentang tujuan baris di sini , di sini , di sini , dan di sini .
Perlu juga dicatat bahwa, jika Anda berbicara tentang SSMS, baris hanya muncul setelah seluruh buffer telah diisi, bukan hanya mau tak mau.
Jika saya mengerti apa yang Anda amati, ini adalah bagaimana Studio Manajemen membuat baris, dan tidak ada hubungannya dengan bagaimana SQL Server mengembalikan baris. Bahkan sering kali ketika Anda mengembalikan hasil besar ke SSMS dan mencoba merendernya dalam kotak, SSMS tidak dapat mengikuti dan SQL Server akhirnya menunggu aplikasi untuk memproses lebih banyak baris. Dalam hal ini Anda akan melihat SQL Server mengumpulkan ASYNC_NETWORK_IO
menunggu.
Anda dapat mengontrolnya dengan menggunakan Hasil ke Teks daripada Hasil ke Kotak, karena SSMS dapat menggambar teks lebih cepat daripada yang bisa menggambar kotak, tetapi Anda mungkin akan menemukan ini dapat mempengaruhi keterbacaan tergantung pada jumlah kolom dan tipe data yang terlibat. Keduanya dipengaruhi oleh ketika SSMS memutuskan untuk benar-benar menulis hasil ke panel itu, yang tergantung pada seberapa penuh buffer output.
Saat Anda memiliki beberapa pernyataan, dan Anda ingin memaksa buffer untuk memberikan hasil keluaran ke panel pesan, Anda bisa menggunakan sedikit trik pencetakan di antara pernyataan:
RAISERROR('', 0, 1) WITH NOWAIT;
Tapi ini tidak akan membantu ketika Anda mencoba untuk mendapatkan SSMS untuk membuat baris lebih cepat ketika semua output berasal dari satu pernyataan.
Lebih langsung, Anda dapat mengontrolnya dengan membatasi berapa banyak hasil yang Anda render dalam SSMS. Saya sering melihat orang mengeluh tentang berapa lama untuk mengembalikan satu juta baris ke grid. Apa yang akan dilakukan seseorang dengan sejuta baris dalam kisi SSMS, saya tidak tahu.
Ada beberapa retas seperti OPTION (FAST 100)
, yang akan dioptimalkan untuk mengambil 100 baris pertama (atau 100 baris jika tidak ada bagian luar ORDER BY
), tetapi ini bisa terjadi dengan biaya pengambilan yang jauh lebih lambat untuk sisa baris dan rencana yang lebih secara keseluruhan tidak efisien, jadi bukan benar-benar pilihan IMHO.
Pertanyaan Anda bukan tentang SQLServer, tetapi:
Apakah ada cara untuk mengendalikan ini?
Jawaban singkat :
sqlcmd
alih-alih ssms
atau sqlcmd
-mode darissms
Jawaban panjang :
Tentu saja! Tapi tidak satu - prob
sqlcmd
atau dalam sqlcmd
-mode dalam ssms.spid
Anda dan Anda mendapatkan daftar pengaturan sesi lengkap. Bandingkan dengan pengaturan sqlcmd
sesi. Jika tidak ada yang diklik - salin semua pengaturan sesi dari profiler ke skrip kueri Anda, jalankan di sqlcmd
-mode dan secara bertahap beralih pengaturan Anda akan menemukan pelakunya.Semoga berhasil!
Untuk menambahkan jawaban sp_BlitzErik, ambil contoh menggunakan NOT IN ()
sub dengan pilih. Untuk menentukan apakah suatu item dalam hasil query bersarang, itu (umumnya) perlu untuk mengambil seluruh hasil.
Jadi salah satu cara mudah yang saya temukan untuk meningkatkan kinerja permintaan seperti itu adalah menulis ulang mereka sebagai LEFT OUTER JOIN
dengan kondisi di mana RIGHT
sisi adalah nol (Anda dapat membalikkannya, tentu saja tetapi siapa yang menggunakan RIGHT OUTER JOINS
?). Ini memungkinkan hasil mulai kembali segera.
WHERE t.x IN (<complex SELECT subquery>)
KIRI LEFT JOIN (<complex SELECT subquery>) AS r ON r.x = t.x .... WHERE r.x IS NULL
KIRIM yang setara ,, maka subquery juga akan dievaluasi, juga (jadi rencana kompleks yang sama dengan NOT Dalam versi).
NOT EXISTS
tetapi Oracle NOT IN
dalam kueri. Tapi hari ini itu harus dianggap sebagai kesalahan dalam generator rencana