Saat Anda memiliki kueri atau prosedur tersimpan yang membutuhkan penyetelan kinerja, apa saja hal pertama yang Anda coba?
sql
sql-server
database
performance
Terrapin
sumber
sumber
Jawaban:
Berikut adalah daftar berguna yang selalu saya berikan kepada seseorang yang bertanya kepada saya tentang pengoptimalan.
Kami terutama menggunakan Sybase, tetapi sebagian besar saran akan berlaku di seluruh papan.
SQL Server, misalnya, dilengkapi dengan sejumlah bit pemantauan / penyetelan kinerja, tetapi jika Anda tidak memiliki yang seperti itu (dan mungkin bahkan jika Anda melakukannya) maka saya akan mempertimbangkan yang berikut ...
99% masalah yang saya lihat disebabkan oleh menempatkan terlalu banyak tabel dalam suatu gabungan . Perbaikan untuk ini adalah dengan melakukan setengah dari gabungan (dengan beberapa tabel) dan menyimpan hasilnya dalam tabel sementara. Kemudian lakukan sisa kueri yang bergabung di tabel sementara itu.
Daftar Periksa Pengoptimalan Permintaan
#temp
tabel mungkin berkinerja lebih baik daripada@table
variabel dengan volume besar (ribuan baris).sumber
sumber
Agak topik, tetapi jika Anda memiliki kontrol atas masalah ini ...
Tingkat tinggi dan Dampak Tinggi
sumber
CREATE INDEX
Yakinkan ada indeks yang tersedia untuk Anda
WHERE
danJOIN
klausa. Ini akan sangat mempercepat akses data.Jika lingkungan Anda adalah data mart atau gudang, indeks harus berlimpah untuk hampir semua permintaan yang mungkin.
Dalam lingkungan transaksional , jumlah indeks harus lebih rendah dan definisinya lebih strategis sehingga pemeliharaan indeks tidak menurunkan sumber daya. (Pemeliharaan indeks adalah ketika daun indeks harus diubah untuk mencerminkan perubahan dalam tabel yang mendasarinya, seperti dengan
INSERT, UPDATE,
danDELETE
operasi.)Selain itu, perhatikan urutan bidang dalam indeks - bidang yang lebih selektif (kardinalitas lebih tinggi), yang lebih awal dalam indeks akan muncul. Misalnya, Anda meminta mobil bekas:
Harga umumnya memiliki kardinalitas yang lebih tinggi. Mungkin hanya ada beberapa lusin warna yang tersedia, tetapi sangat mungkin ribuan harga yang diminta berbeda.
Dari pilihan indeks ini,
idx01
berikan jalur yang lebih cepat untuk memenuhi kueri:Ini karena lebih sedikit mobil yang akan memenuhi titik harga daripada pilihan warna, memberikan mesin kueri data yang jauh lebih sedikit untuk dianalisis.
Saya dikenal memiliki dua indeks yang sangat mirip, hanya berbeda di bidang untuk mempercepat kueri (nama depan, nama belakang) dalam satu dan (nama belakang, nama depan) di yang lain.
sumber
Trik yang baru-baru ini saya pelajari adalah bahwa SQL Server dapat memperbarui variabel lokal serta bidang, dalam pernyataan pembaruan.
Atau versi yang lebih mudah dibaca:
Saya telah menggunakan ini untuk mengganti kursor / gabungan yang rumit ketika menerapkan perhitungan rekursif, dan juga mendapatkan banyak kinerja.
Berikut detail dan contoh kode yang membuat peningkatan fantastis dalam kinerja: http://geekswithblogs.net/Rhames/archive/2008/10/28/calculating-running-totals-in-sql-server-2005---the-optimal. aspx
sumber
Dengan asumsi MySQL di sini, gunakan EXPLAIN untuk mencari tahu apa yang terjadi dengan kueri, pastikan bahwa indeks digunakan seefisien mungkin dan mencoba untuk menghilangkan jenis file. MySQL Berkinerja Tinggi: Optimasi, Cadangan, Replikasi, dan Lainnya adalah buku yang hebat tentang topik ini seperti halnya Blog Kinerja MySQL .
sumber
@Terrapin ada beberapa perbedaan lain antara isnull dan penggabungan yang layak disebutkan (selain kepatuhan ANSI, yang merupakan hal besar bagi saya).
Coalesce vs IsNull
sumber
Terkadang dalam SQL Server jika Anda menggunakan ATAU di mana klausa itu benar-benar akan mendongkrak kinerja. Alih-alih menggunakan ATAU, lakukan saja dua pemilihan dan satukan keduanya. Anda mendapatkan hasil yang sama dengan kecepatan 1000x.
sumber
Lihatlah klausa mana - verifikasi penggunaan indeks / verifikasi tidak ada yang konyol sedang dilakukan
sumber
Saya biasanya akan mulai dengan gabungan - saya akan mengetuk masing-masing dari kueri satu per satu dan menjalankan kembali kueri untuk mendapatkan ide jika ada gabung tertentu yang bermasalah dengan saya.
sumber
Pada semua tabel temp saya, saya ingin menambahkan batasan unik (jika perlu) untuk membuat indeks, dan kunci utama (hampir selalu).
sumber
Saya sudah terbiasa untuk selalu menggunakan variabel bind. Mungkin variabel terikat tidak akan membantu jika RDBMS tidak men-cache pernyataan SQL. Tetapi jika Anda tidak menggunakan variabel bind, RDBMS tidak memiliki kesempatan untuk menggunakan kembali rencana eksekusi permintaan dan menguraikan pernyataan SQL. Penghematan bisa sangat besar: http://www.akadia.com/services/ora_bind_variables.html . Saya bekerja sebagian besar dengan Oracle, tetapi Microsoft SQL Server bekerja dengan cara yang hampir sama.
Dalam pengalaman saya, jika Anda tidak tahu apakah Anda menggunakan variabel mengikat atau tidak, Anda mungkin tidak. Jika bahasa aplikasi Anda tidak mendukungnya, temukan yang mendukung. Terkadang Anda dapat memperbaiki kueri A dengan menggunakan variabel bind untuk kueri B.
Setelah itu, saya berbicara dengan DBA kami untuk mencari tahu apa yang paling menyebabkan rasa sakit pada RDBMS. Perhatikan bahwa Anda seharusnya tidak bertanya "Mengapa permintaan ini lambat?" Itu seperti meminta dokter Anda untuk mengambil Anda lampiran. Tentu kueri Anda mungkin masalahnya, tetapi kemungkinan besar ada sesuatu yang salah. Sebagai pengembang, kami cenderung berpikir dalam hal baris kode. Jika saluran lambat, perbaiki jalur itu. Tetapi RDBMS adalah sistem yang sangat rumit dan permintaan Anda yang lambat mungkin merupakan gejala dari masalah yang jauh lebih besar.
Terlalu banyak tips tuning SQL adalah berhala pemujaan kargo. Sebagian besar masalah tidak terkait atau minimal terkait dengan sintaks yang Anda gunakan, jadi biasanya yang terbaik adalah menggunakan sintaks terbersih yang Anda bisa. Kemudian Anda bisa mulai mencari cara untuk menyempurnakan basis data (bukan kueri). Hanya men-tweak sintaks ketika itu gagal.
Seperti penyetelan kinerja, selalu kumpulkan statistik yang berarti. Jangan gunakan waktu jam dinding kecuali itu adalah pengalaman pengguna yang sedang Anda setel. Alih-alih melihat hal-hal seperti waktu CPU, baris diambil dan blok pembacaan disk. Terlalu sering orang mengoptimalkan untuk hal yang salah.
sumber
Langkah pertama: Lihatlah Rencana Eksekusi Kueri!
TableScan ->
NestedLoop buruk -> peringatan meh
TableScan di belakang NestedLoop -> DOOM!
SET STATISTIK IO ON
SET STATISTICS TIME ON
sumber
Menjalankan kueri menggunakan WITH (NoLock) cukup banyak operasi standar di tempat saya. Siapa pun yang ketahuan menjalankan kueri pada tabel puluhan gigabytes tanpa dikeluarkan dan ditembak.
sumber
Konversikan BUKAN kueri menjadi LEFT OUTER GABUNG jika memungkinkan. Misalnya jika Anda ingin menemukan semua baris di Table1 yang tidak digunakan oleh kunci asing di Table2 Anda bisa melakukan ini:
Tetapi Anda mendapatkan kinerja yang jauh lebih baik dengan ini:
sumber
@ DavidM
Dalam SQL Server, rencana eksekusi memberi Anda hal yang sama - ia memberi tahu Anda indeks apa yang dipukul, dll.
sumber
Buat indeks tabel berdasarkan clm yang Anda filter
sumber
Tidak harus trik kinerja SQL per se tetapi pasti terkait:
Sebaiknya gunakan memcached jika mungkin karena akan jauh lebih cepat hanya dengan mengambil data yang sudah dikompilasi langsung dari memori daripada mendapatkannya dari database. Ada juga rasa MySQL yang memcached built in (pihak ketiga).
sumber
Pastikan panjang indeks Anda sekecil mungkin. Ini memungkinkan DB untuk membaca lebih banyak kunci sekaligus dari sistem file, sehingga mempercepat penggabungan Anda. Saya menganggap ini bekerja dengan semua DB, tapi saya tahu ini adalah rekomendasi khusus untuk MySQL.
sumber
Saya mencari:
sumber
Biasanya baris pertama di dalam prosedur tersimpan saya, kecuali saya benar-benar perlu menggunakan
@@ROWCOUNT
.sumber
Dalam SQL Server, gunakan direktif nolock. Ini memungkinkan perintah pilih untuk selesai tanpa harus menunggu - biasanya transaksi lainnya selesai.
sumber
Hapus kursor di mana pun tidak diperlukan.
sumber
Hapus panggilan fungsi di Sprocs di mana banyak baris akan memanggil fungsi.
Kolega saya menggunakan panggilan fungsi (dapatkan lastlogindate dari userid sebagai contoh) untuk mengembalikan recordset yang sangat luas.
Ditugasi dengan pengoptimalan, saya mengganti pemanggilan fungsi dalam sproc dengan kode fungsi: Saya mendapatkan banyak waktu sprocs 'berjalan dari> 20 detik menjadi <1.
sumber
sumber
Saya suka menggunakan
Lebih
Ketika saya tidak membutuhkan dukungan banyak argumen yang menyatu memberi Anda.
http://blog.falafel.com/2006/04/05/SQLServerArcanaISNULLVsCOALESCE.aspx
sumber
Jangan awali nama Prosedur Tersimpan dengan "sp_" karena semua prosedur sistem dimulai dengan "sp_", dan SQL Server harus mencari lebih keras untuk menemukan prosedur Anda ketika dipanggil.
sumber
Kotor berbunyi -
Mencegah kunci mati di mana integritas transaksional tidak mutlak diperlukan (yang biasanya benar)
sumber
Saya selalu pergi ke SQL Profiler (jika ini adalah prosedur tersimpan dengan banyak tingkat bersarang) atau perencana pelaksanaan kueri (jika itu beberapa pernyataan SQL tanpa bersarang) terlebih dahulu. 90% dari waktu Anda dapat segera menemukan masalah dengan salah satu dari dua alat ini.
sumber