Perusahaan saya menggunakan aplikasi yang memiliki masalah kinerja yang cukup besar. Ada beberapa masalah dengan database itu sendiri yang sedang dalam proses saya kerjakan, tetapi banyak masalah yang terkait aplikasi murni.
Dalam investigasi saya, saya menemukan bahwa ada jutaan query yang mengenai database SQL Server yang meminta tabel kosong. Kami memiliki sekitar 300 tabel kosong dan beberapa dari tabel tersebut dipertanyakan hingga 100-200 kali per menit. Tabel tidak ada hubungannya dengan area bisnis kami dan pada dasarnya adalah bagian dari aplikasi asli yang tidak dihapus oleh vendor ketika mereka dikontrak oleh perusahaan saya untuk menghasilkan solusi perangkat lunak bagi kami.
Terlepas dari kenyataan bahwa kami mencurigai log kesalahan aplikasi kami dibanjiri dengan kesalahan yang terkait dengan masalah ini, vendor meyakinkan kami bahwa tidak ada dampak kinerja atau stabilitas baik untuk aplikasi atau server database. Log kesalahan dibanjiri sejauh kita tidak dapat melihat lebih dari 2 menit kesalahan untuk melakukan diagnosa.
Biaya sebenarnya dari pertanyaan ini jelas akan rendah dalam hal siklus CPU dll. Tapi adakah yang bisa menyarankan apa efeknya pada SQL Server dan aplikasi? Saya akan curiga bahwa mekanisme pengiriman permintaan, konfirmasi, pemrosesan, pengembalian, dan penerimaan tanda terima oleh aplikasi itu sendiri akan berdampak pada kinerja.
Kami menggunakan SQL Server 2008 R2, Oracle Weblogic 11g untuk aplikasi.
@ Frisbee- Singkatnya, saya membuat tabel berisi querytext yang mengenai tabel-tabel kosong di basis data aplikasi, lalu menanyakannya untuk semua nama yang saya tahu kosong dan mendapat daftar yang sangat panjang. Hit tertinggi adalah pada 2,7 juta eksekusi selama 30 hari uptime, mengingat aplikasi ini umumnya digunakan pada jam 8 pagi - 6 sore sehingga angka-angka itu lebih terkonsentrasi pada jam operasional. Beberapa tabel, beberapa kueri, mungkin beberapa relavent via gabungan, beberapa tidak. Hit teratas (2,7 juta pada saat itu) adalah pemilihan sederhana dari satu tabel kosong dengan klausa di mana, tanpa gabungan. Saya mengharapkan pertanyaan yang lebih besar dengan bergabung ke tabel kosong mungkin termasuk pembaruan ke tabel tertaut, tetapi saya akan memeriksanya dan memperbarui pertanyaan ini secepatnya.
Pembaruan: Ada 1000 pertanyaan dengan jumlah eksekusi antara 1043 - 4622614 (lebih dari 2,5 bulan). Saya harus menggali lebih banyak untuk mengetahui kapan rencana cache berasal dari. Ini hanya untuk memberi Anda gambaran tentang tingkat pertanyaan. Sebagian besar cukup rumit dengan lebih dari 20 bergabung.
@ srutzky- ya saya percaya ada kolom tanggal terkait ketika rencana itu disusun sehingga akan menarik, jadi saya akan memeriksanya. Saya ingin tahu apakah batas utas menjadi faktor sama sekali ketika SQL Server duduk di kluster VMware? Segera menjadi Dell PE 730xD yang berdedikasi untungnya.
@Frisbee - Maaf atas tanggapan yang terlambat. Seperti yang Anda sarankan, saya menjalankan pilih * dari tabel kosong 10.000 kali lebih dari 24 utas menggunakan SQLQueryStress (jadi sebenarnya 240.000 iterasi) dan tekan 10.000 Permintaan Batch / detik segera. Kemudian saya berkurang menjadi 1000 kali lebih dari 24 utas dan mencapai kurang dari 4.000 Permintaan Batch / detik. Saya juga mencoba 10.000 iterasi dengan hanya 12 thread (jadi total iterasi 1.200) dan ini menghasilkan 6.505 Batch berkelanjutan / detik. Efek pada CPU sebenarnya terlihat, sekitar 5-10% dari total penggunaan CPU selama setiap pengujian berjalan. Jaringan menunggu dapat diabaikan (seperti 3ms dengan klien di workstation saya) tetapi dampak CPU ada di sana, yang cukup meyakinkan sejauh yang saya ketahui. Tampaknya bermuara pada penggunaan CPU dan sedikit file database IO yang tidak perlu. Total eksekusi / detik bekerja di bawah 3000, yang lebih dari produksi, namun saya menguji hanya satu dari puluhan pertanyaan seperti ini. Efek bersih dari ratusan kueri yang mengenai tabel kosong dengan kecepatan antara 300-4000 kali per menit karenanya tidak akan diabaikan ketika menyangkut waktu CPU. Semua pengujian dilakukan terhadap idle PE 730xD dengan dual flash array dan 256GB RAM, 12 core modern.
@ srutzky- pemikiran yang bagus. SQLQueryStress tampaknya menggunakan pooling koneksi secara default, tetapi saya telah melihat pula dan menemukan bahwa ya, kotak untuk pooling koneksi diperiksa. Perbarui untuk mengikuti
@ srutzky- Kumpulan koneksi tampaknya tidak diaktifkan pada aplikasi - atau jika itu, itu tidak berfungsi. Saya melakukan penelusuran profiler dan menemukan bahwa koneksi memiliki EventSubClass "1 - Nonpooled" untuk acara Login Audit.
RE: Connection Pooling- Memeriksa weblogics dan menemukan pooling koneksi diaktifkan. Berlari lebih banyak jejak terhadap hidup dan menemukan tanda-tanda pengumpulan tidak terjadi dengan benar / sama sekali:
Dan di sini adalah seperti apa ketika saya menjalankan permintaan tunggal tanpa bergabung dengan tabel yang dihuni; pengecualian berbunyi "Galat terkait jaringan atau contoh khusus terjadi saat membuat koneksi ke SQL Server. Server tidak ditemukan atau tidak dapat diakses. Pastikan nama instance sudah benar dan bahwa SQL Server dikonfigurasi untuk memungkinkan koneksi jarak jauh. (penyedia: Penyedia Pipa Bernama, kesalahan: 40 - Tidak dapat membuka koneksi ke SQL Server) "Perhatikan penghitung permintaan batch. Ping server selama waktu pengecualian dihasilkan menghasilkan respons ping yang sukses.
Pembaruan - dua pengujian berturut-turut berjalan, beban kerja yang sama (pilih * dariEmptyTable), pengumpulan diaktifkan / tidak diaktifkan. Penggunaan CPU sedikit lebih banyak dan banyak kegagalan dan tidak pernah melampaui permintaan batch 500 / detik. Pengujian menunjukkan 10.000 Batch / detik dan tidak ada kegagalan dengan pooling ON, dan sekitar 400 batch / detik maka banyak kegagalan karena pooling dinonaktifkan. Saya ingin tahu apakah kegagalan ini terkait dengan kurangnya ketersediaan koneksi?
@ srutzky- Pilih Hitungan (*) dari sys.dm_exec_connections;
Pooling diaktifkan: 37 secara konsisten, bahkan setelah tes beban berhenti
Pooling dinonaktifkan: 11-37 tergantung pada ada atau tidaknya pengecualian
pada SQLQueryStress yaitu: ketika palung tersebut muncul pada
grafik Batch / sec, pengecualian terjadi pada SQLQueryStress, dan
jumlah koneksi turun menjadi 11, kemudian secara bertahap kembali ke 37 ketika bets mulai memuncak dan pengecualian tidak terjadi. Sangat, sangat menarik.
Koneksi maksimum pada kedua instance uji / langsung ditetapkan pada default 0.
Telah memeriksa log aplikasi dan tidak dapat menemukan masalah konektivitas, hanya ada beberapa menit logging yang tersedia karena jumlah besar dan ukuran kesalahan yaitu: banyak kesalahan jejak stack. Seorang kolega pada dukungan aplikasi menyarankan bahwa sejumlah besar kesalahan HTTP terjadi terkait dengan konektivitas. Tampaknya berdasarkan ini, bahwa untuk beberapa alasan aplikasi tidak mengumpulkan koneksi secara benar dan sebagai hasilnya, server berulang kali kehabisan koneksi. Saya akan melihat log aplikasi lebih lanjut. Saya bertanya-tanya apakah ada cara untuk membuktikan ini terjadi dalam produksi dari sisi SQL Server?
@ srutzky- Terima kasih. Saya akan memeriksa konfigurasi weblogik besok dan memperbarui. Namun saya berpikir tentang 37 koneksi belaka - jika SQLQueryStress melakukan 12 utas pada 10.000 iterasi = 120.000 pernyataan pilih yang tidak digabungkan, bukankah itu berarti setiap pilih membuat koneksi yang berbeda ke instance sql?
@ srutzky- Weblogics dikonfigurasikan ke koneksi pool, jadi seharusnya berfungsi dengan baik. Kumpulan koneksi dikonfigurasikan seperti ini, di masing-masing dari 4 weblog yang seimbang:
- Kapasitas awal: 10
- Kapasitas Maksimal: 50
- Kapasitas Minimum: 5
Ketika saya meningkatkan jumlah utas yang menjalankan kueri pemilihan dari tabel kosong, jumlah koneksi mencapai sekitar 47. Dengan penyatuan koneksi dinonaktifkan, saya secara konsisten melihat permintaan batch yang lebih rendah / detik (dari 10.000 turun menjadi sekitar 400). Apa yang akan terjadi setiap saat adalah bahwa 'pengecualian' pada SQLQueryStress terjadi tidak lama setelah batch / detik masuk ke palung. Ini terkait dengan konektivitas tetapi saya tidak dapat memahami mengapa ini terjadi. Ketika tidak ada tes yang berjalan, # koneksi turun menjadi sekitar 12.
Dengan koneksi pool dinonaktifkan, saya mengalami kesulitan memahami mengapa pengecualian terjadi, tapi mungkin itu seluruh pertanyaan stackExchange lainnya / pertanyaan untuk Adam Machanic?
@rutzky Saya bertanya-tanya mengapa pengecualian terjadi tanpa pooling diaktifkan, meskipun SQL Server tidak kehabisan koneksi?
SELECT COUNT(*) FROM sys.dm_exec_connections;
untuk melihat apakah nilainya sangat berbeda antara mengaktifkan penyatuan atau tidak. Berdasarkan kesalahan itu, saya pikir akan ada lebih banyak koneksi ketika pooling dinonaktifkan.Pooling=false
atauMax Pool Size
?Jawaban:
Ya, dan bahkan ada beberapa faktor tambahan, tetapi sejauh mana semua ini benar-benar memengaruhi sistem Anda, tidak mungkin dikatakan tanpa menganalisis sistem.
Yang sedang berkata, Anda meminta apa yang bisa menjadi masalah, dan ada beberapa hal untuk disebutkan, bahkan jika beberapa di antaranya saat ini tidak menjadi faktor dalam situasi khusus Anda. Itu kata kamu:
Bahkan mungkin ada lebih banyak, tetapi ini akan membantu memahami beberapa hal. Dan perlu diingat bahwa seperti kebanyakan masalah kinerja, itu semua masalah skala. Semua item yang disebutkan di atas tidak menjadi masalah jika dipukul sekali per menit. Ini seperti menguji perubahan pada workstation Anda atau dalam database pengembangan: itu selalu berfungsi dengan hanya 10 - 100 baris dalam tabel. Pindahkan kode itu ke produksi dan butuh 10 menit untuk berjalan, dan seseorang pasti akan mengatakan: "baik, ia bekerja di kotak saya" ;-). Artinya, itu hanya karena banyaknya panggilan yang dilakukan sehingga Anda melihat masalah, tetapi itulah situasi yang ada.
Jadi, bahkan pada 1 juta query 0 baris yang tidak berguna, itu berjumlah:
lebih banyak koneksi dipertahankan yang membutuhkan lebih banyak memori. Berapa banyak RAM fisik yang tidak terpakai yang Anda miliki? memori itu akan lebih baik digunakan untuk menjalankan kueri dan / atau cache rencana kueri. Kasus terburuk adalah bahwa Anda kehabisan memori fisik dan SQL Server harus mulai menggunakan memori virtual (swap), karena memperlambat segalanya (periksa log galat SQL Server Anda untuk melihat apakah Anda mendapatkan pesan tentang memori yang sedang dipetakan).
Dan kalau-kalau ada yang menyebutkan, "well, ada koneksi pooling". Ya, itu pasti membantu mengurangi jumlah koneksi yang dibutuhkan. Tetapi dengan pertanyaan yang masuk hingga 200 kali per menit, itu adalah banyak aktivitas bersamaan dan koneksi masih perlu ada untuk permintaan yang sah. Lakukan
SELECT * FROM sys.dm_exec_connections;
untuk melihat berapa banyak koneksi aktif yang Anda pertahankan.Jika saya tidak salah tentang apa yang saya nyatakan di sini, maka bagi saya tampaknya, bahkan dalam skala kecil, ini adalah jenis serangan DDoS pada sistem Anda karena membanjiri jaringan dan SQL Server Anda dengan permintaan palsu , mencegah permintaan nyata dari mendapatkan ke SQL Server atau sedang diproses oleh SQL Server.
sumber
Jika tabel mendapatkan hit 100-200 kali per menit maka mereka (mudah-mudahan) dalam memori. Beban di server sangat sangat rendah. Kecuali Anda memiliki CPU atau memori tinggi pada server database, ini kemungkinan tidak menjadi masalah.
Ya kueri mengambil kunci bersama tetapi mudah-mudahan tidak memblokir kunci pembaruan apa pun atau diblokir oleh kunci pembaruan apa pun. Apakah Anda memiliki pembaruan, masukkan, atau hapus pada tabel ini. Jika tidak, saya hanya akan membiarkannya pergi - jika Anda mengalami masalah kinerja harus ada ikan yang lebih besar untuk digoreng dari perspektif server database.
Saya menjalankan tes pada 100.000 hitungan pilih (*) di atas meja kosong dan itu berjalan dalam 32 detik dan pertanyaannya melalui jaringan. Jadi 1/3 milidetik. Kecuali jaringan Anda kelebihan beban, ini bahkan tidak berdampak pada klien. Jika Anda mengalami masalah kinerja utama, kueri kosong 1/3 milidetik ini bukanlah yang mematikan aplikasi.
Dan ini bisa saja bagian dari join kiri yang mengambil beberapa tipe data statis yang bukan bagian dari aplikasi saat ini. Bisa dirantai dengan pertanyaan lain sehingga bukan perjalanan pulang-pergi tambahan. Jika demikian ya itu ceroboh tetapi bahkan tidak menyebabkan lebih banyak lalu lintas.
Jadi kembali untuk melihat pernyataan yang sebenarnya. Apakah Anda melihat pembaruan, penambahan, atau penghapusan pada tabel ini?
Ya, banyak tabel kosong dan kueri ke tabel kosong merupakan indikasi pengkodean yang ceroboh. Tetapi jika Anda memiliki masalah kinerja utama ini bukan penyebabnya kecuali Anda memiliki beberapa operasi penulisan yang ceroboh juga terjadi dengan tabel ini.
sumber
Secara umum pada setiap permintaan, langkah-langkah berikut dilakukan:
banyak pertanyaan seperti yang Anda sebutkan mungkin menyebabkan beban tambahan pada sistem yang sudah berat - beban tambahan pada koneksi, CPU, RAM dan I / O.
sumber