Kami memiliki database untuk produk yang berat-menulis. Kami baru saja membeli mesin server baru dengan SSD untuk membantu. Yang mengejutkan kami, pemasangannya tidak lebih cepat dari pada mesin lama kami dengan penyimpanan yang jauh lebih lambat. Selama benchmarking kami perhatikan bahwa tingkat IO yang ditunjukkan oleh proses SQL Server sangat rendah.
Misalnya, saya menjalankan skrip yang ditemukan di halaman ini , kecuali bahwa saya menambahkan BEGIN TRAN dan COMMIT di sekitar loop. Paling-paling saya bisa melihat penggunaan disk mencapai 7Mb / s, sementara CPU hampir tidak menyentuh 5%. Server telah menginstal 64Gb dan menggunakan 10. Waktu menjalankan total adalah 2 menit 15 detik untuk panggilan pertama turun menjadi sekitar 1 menit untuk panggilan berikutnya. Basis data sedang dalam pemulihan sederhana dan tidak digunakan selama pengujian. Saya menjatuhkan meja di antara setiap panggilan.
Mengapa skrip sederhana ini begitu lambat? Perangkat kerasnya hampir tidak digunakan sama sekali. Kedua alat pembandingan disk khusus dan SQLIO menunjukkan bahwa SSD berkinerja dengan benar dengan kecepatan hingga 500Mb / dtk untuk membaca dan menulis. Saya mengerti bahwa menulis acak lebih lambat dari menulis berurutan, tapi saya berharap insert sederhana seperti ini, ke tabel tanpa pengindeksan berkelompok, menjadi jauh lebih cepat.
Pada akhirnya skenario kami jauh lebih kompleks, tetapi saya merasa perlu memahami kasus sederhana terlebih dahulu. Singkatnya aplikasi kita menghapus data lama, kemudian menggunakan SqlBulkCopy untuk menyalin data baru ke staging tables, melakukan beberapa penyaringan, dan akhirnya menggunakan MERGE dan / atau INSERT INTO tergantung pada kasus untuk menyalin data ke tabel akhir.
-> EDIT 1: Saya mengikuti prosedur yang ditautkan oleh Martin Smith, dan saya mendapatkan hasil sebagai berikut:
[Wait Type] [Wait Count] [Total Wait (ms)] [T. Resource Wait (ms)] [T. Signal Wait (ms)]
NETWORK_IO 5008 46735 46587 148
LOGBUFFER 901 5994 5977 17
PAGELATCH_UP 40 866 865 1
SOS_SCHEDULER_YIELD 53279 219 121 98
WRITELOG 5 145 145 0
PAGEIOLATCH_UP 4 58 58 0
LATCH_SH 5 0 0 0
Saya merasa aneh NETWORK_IO mengambil sebagian besar waktu, mengingat tidak ada hasil untuk ditampilkan dan tidak ada data untuk ditransfer di mana pun selain ke file SQL. Apakah tipe NETWORK_IO mencakup semua IO?
-> EDIT 2: Saya membuat disk RAM 20Gb dan memasang basis data dari sana. Waktu terbaik yang saya miliki di SSD adalah 48 detik, dengan disk RAM turun menjadi 37 detik. NETWORK_IO masih menunggu terbesar. Kecepatan tulis maksimum ke disk RAM adalah sekitar 250Mb / s sementara itu mampu melakukan multi gigabytes per detik. Masih tidak menggunakan banyak CPU, jadi apa yang menahan SQL?
SET NOCOUNT ON
juga.NETWORK_IO
mungkin dari 3 juta "1 baris (s) terpengaruh" pesan-pesan yang dikirim kembali. Apakah Anda mencoba menambahkanSET NOCOUNT ON
ke skrip?EE_WaitStats*.xel
sehingga yang lama akan mencemari hasil Anda.Jawaban:
Saya tahu ini adalah pertanyaan lama tetapi ini mungkin masih membantu para pencari dan ini adalah masalah yang muncul setiap saat.
Alasan utama mengapa Anda menekan langit-langit kinerja tanpa Anda melihat hambatan sumber daya adalah karena Anda telah mencapai batas apa yang mungkin untuk diproses dalam satu thread tunggal sesi. Loop tidak diproses secara paralel, tetapi semua insert dilakukan secara serial.
Dalam kasus saya, dibutuhkan 36 detik untuk memasukkan 3 juta baris. Itu berarti 36/30000000 = 0,000012 detik per baris. Itu cukup cepat. Di sistem saya, hanya dibutuhkan 0,000012 untuk melalui semua langkah yang diperlukan.
Satu-satunya cara untuk menyelesaikannya lebih cepat adalah memulai sesi kedua secara paralel.
Jika saya memulai 2 sesi secara paralel, keduanya melakukan 15 juta sisipan. Keduanya selesai dalam 18 detik. Saya dapat meningkatkan skala, tetapi pengaturan pengujian saya saat ini mencapai 95% cpu dengan dua sesi paralel, jadi melakukan 3 akan memusingkan hasilnya karena saya akan mengalami hambatan CPU.
Jika saya memulai 2 sesi paralel keduanya menyisipkan 3 juta baris, keduanya selesai dalam 39 detik. jadi sekarang 6 juta baris dalam 39 detik.
Oke, itu masih meninggalkan kita dengan menunggu NETWORK_IO muncul.
Tunggu NETWORK_IO ditambahkan oleh fakta bahwa Anda menggunakan peristiwa yang diperluas untuk melacaknya. Dalam kasus saya, insert membutuhkan waktu 36 detik (rata-rata). Saat menggunakan cara acara yang diperluas (dari tautan di atas di komentar pertama) inilah yang terdaftar:
Anda dapat melihat bahwa 68 detik NETWORK_IO terdaftar. Tetapi karena loop insert adalah tindakan berulir tunggal yang memerlukan waktu 36 detik, ini tidak mungkin. (Ya, banyak utas digunakan, tetapi operasinya serial, tidak pernah paralel, sehingga Anda tidak dapat mengakumulasi lebih banyak waktu tunggu daripada total durasi kueri)
Jika saya tidak menggunakan acara yang diperpanjang tetapi hanya menunggu DMVs statistik pada contoh yang tenang (hanya dengan saya menjalankan sisipan) Saya mendapatkan ini:
Jadi NETWORK_IO yang Anda lihat di log peristiwa yang diperluas, tidak terkait dengan loop sisipan Anda. (Jika Anda tidak mengaktifkan nocount, Anda akan memiliki IO jaringan async besar, +1 Martin)
Namun saya tidak tahu mengapa NETWORK_IO muncul di jejak acara yang diperluas. Tentu saja penulisan target file async dari peristiwa tersebut mengakumulasi ASYNC_NETWORK_IO, tetapi tentunya ini semua dilakukan pada SPID yang berbeda dari yang kami filter. Saya mungkin mengajukan ini sebagai pertanyaan baru sendiri)
sumber
Biasanya Anda mulai dengan melihat
sys.dm_exec_requests
, khususnya padawait_time
,wait_type
danwait_resource
untuk permintaan INSERT Anda. Ini akan memberikan indikasi yang jelas apa yang menghalangi INSERT Anda. Hasil akan menunjukkan apakah pertikaian kunci, peristiwa pertumbuhan file, menunggu log flush, pertikaian alokasi (dimanifestasikan sebagai pertengkaran kait halaman PFS) dll. Dll. Setelah Anda mengukur, perbarui pertanyaan Anda sesuai. Saya sangat menyarankan Anda untuk berhenti sekarang dan membaca metodologi pemecahan masalah Tunggu dan Antrian sebelum Anda melanjutkan.sumber
Saya menjalankan skrip uji pada halaman yang terhubung dalam OP dengan BEGIN TRAN / COMMIT di sekitar loop. Di komputer saya, dibutuhkan 1:28 untuk menyelesaikan pertama kalinya.
Lalu saya memindahkan dua perintah ini di luar loop:
Itu selesai dalam 28 detik setelah itu.
Saya tidak tahu pasti apa yang terjadi, tapi saya kira mungkin ada semacam tidur dalam
RAND()
kode, mungkin sebagai bagian dari algoritma yang mereka gunakan untuk menghasilkan entropi (angka acak yang lebih baik).FWIW, SSD tidak selalu merupakan teknologi terbaik untuk aplikasi yang berat. Untuk kinerja terbaik, pastikan log DB Anda menggunakan huruf drive berbeda dari data DB, file log sudah dipra-tumbuh hingga ukuran maksimumnya, dan jangan pernah memotong log.
sumber
DMV lain yang saya gunakan untuk mengidentifikasi kelambatan adalah sys.dm_os_waiting_tasks . Jika permintaan Anda bukan CPU intensif, maka Anda dapat menemukan informasi lebih lanjut tentang menunggu dari DMV ini.
sumber
Saya memeriksa daftar acara tunggu untuk sql 2008 dan saya tidak melihat NETWORK_IO terdaftar: http://technet.microsoft.com/en-us/library/ms179984(v=sql.100).aspx
Saya pikir NETWORK_IO sekarang baru saja terdaftar sebagai ASYNC_NETWORK_IO, jadi saya ingin bertanya apakah Anda dapat memeriksa versi SQL Anda lagi, karena saya hanya ingin tahu bagaimana / mengapa acara tunggu itu muncul untuk versi itu.
Adapun menunggu jaringan muncul sama sekali, ya itu bisa terjadi bahkan jika Anda bekerja pada server mandiri. Sudahkah Anda memeriksa pengaturan untuk kartu jaringan Anda? Saya bertanya-tanya apakah itu masalah.
Pada akhirnya, hanya ada beberapa hambatan sumber daya yang mungkin: memori, CPU, disk I / O, jaringan, dan penguncian. Anda telah mengindikasikan bahwa CPU dan I / O bukan masalahnya, dan Anda memiliki acara tunggu NETWORK_IO, jadi saya sarankan Anda melihat kartu NIC tersebut terlebih dahulu.
sumber
NETWORK_IO
ditampilkan karena OP menggunakan acara yang diperluas. Itu tidak pernah diperbarui disys.dm_xe_map_values