Di banyak beban kerja SQL Server, terutama OLTP, log transaksi database dapat menjadi hambatan yang menambah waktu yang diperlukan untuk menyelesaikan transaksi. Kebanyakan orang berasumsi bahwa subsistem I/O adalah hambatan yang sebenarnya, karena tidak mampu mengimbangi jumlah log transaksi yang dihasilkan oleh beban kerja.
Latensi Tulis Log Transaksi
Latensi operasi tulis ke log transaksi dapat dipantau menggunakan sys.dm_io_virtual_file_stats
DMV dan dikorelasikan dengan WRITELOG
menunggu yang terjadi pada sistem. Saya merekam video demo menganalisis log transaksi I/O pada tahun 2011 jadi saya tidak akan mengulangi semuanya di posting ini. Anda bisa mendapatkan videonya di sini dan kode demonya di sini (cocok untuk langsung dijalankan dalam produksi).
Jika latensi tulis lebih tinggi dari yang Anda harapkan untuk subsistem I/O Anda, maka subsistem I/O tidak dapat mengikuti, seperti anggapan umum. Apakah itu berarti bahwa subsistem I/O perlu ditingkatkan? Belum tentu.
Pada banyak sistem klien, saya menemukan bahwa sebagian besar catatan log yang dihasilkan tidak diperlukan, dan jika Anda dapat mengurangi jumlah catatan log yang dihasilkan, Anda mengurangi jumlah log transaksi yang ditulis ke disk. Ini akan menghasilkan pengurangan latensi tulis, sehingga mengurangi waktu penyelesaian transaksi.
Ada dua penyebab utama pembuatan catatan log asing:indeks nonclustered yang tidak digunakan, dan indeks menjadi terfragmentasi.
Indeks Nonclustered yang Tidak Digunakan
Setiap kali catatan dimasukkan ke dalam tabel, catatan harus dimasukkan ke dalam setiap indeks nonclustered yang ditentukan pada tabel (dengan pengecualian indeks yang difilter dengan filter yang sesuai, yang akan saya abaikan dari titik ini). Ini berarti bahwa catatan log tambahan dihasilkan, setidaknya satu per indeks nonclustered, untuk setiap sisipan tabel. Hal yang sama berlaku untuk menghapus catatan dalam tabel - catatan yang cocok harus dihapus dari semua indeks nonclustered. Untuk pembaruan ke catatan tabel, catatan indeks nonclustered hanya diperbarui jika kolom kunci indeks nonclustered atau kolom yang disertakan adalah bagian dari pembaruan.
Operasi ini diperlukan, tentu saja, untuk menjaga setiap indeks nonclustered benar sehubungan dengan tabel, tetapi jika indeks nonclustered tidak digunakan oleh beban kerja, maka operasi dan catatan log yang dihasilkan oleh mereka adalah overhead yang tidak perlu. Selanjutnya, jika indeks yang tidak digunakan ini menjadi terfragmentasi (yang akan saya bahas nanti dalam posting ini), maka tugas pemeliharaan indeks reguler juga akan beroperasi pada indeks tersebut, menghasilkan lebih banyak catatan log (dari indeks REBUILD
atau REORGANIZE
operasi) sama sekali tidak perlu.
Indeks yang tidak digunakan berasal dari berbagai sumber seperti seseorang yang salah membuat indeks per kolom tabel, seseorang yang membuat setiap indeks yang disarankan oleh DMV indeks yang hilang, atau seseorang yang membuat semua indeks yang disarankan oleh Database Tuning Advisor. Mungkin juga karakteristik beban kerja telah berubah sehingga indeks yang dulu berguna tidak lagi digunakan.
Dari mana pun mereka berasal, indeks yang tidak digunakan harus dihapus untuk mengurangi biaya overhead mereka. Anda dapat menentukan indeks mana yang tidak digunakan menggunakan sys.dm_db_index_usage_stats DMV, dan saya sarankan Anda membaca posting rekan saya Kimberly L. Tripp (di sini), dan Joe Sack (di sini dan di sini), karena mereka menjelaskan cara menggunakan DMV dengan benar.
Fragmentasi Indeks
Kebanyakan orang menganggap fragmentasi indeks sebagai masalah yang memengaruhi kueri yang harus membaca data dalam jumlah besar. Meskipun ini adalah salah satu masalah yang dapat disebabkan oleh fragmentasi, fragmentasi juga merupakan masalah karena bagaimana hal itu terjadi.
Fragmentasi disebabkan oleh operasi yang disebut pemisahan halaman. Penyebab paling sederhana dari pemisahan halaman adalah ketika catatan indeks harus dimasukkan pada halaman tertentu (karena nilai kuncinya) dan halaman tidak memiliki cukup ruang kosong. Dalam skenario ini, operasi berikut akan dilakukan:
- Halaman indeks baru dialokasikan dan diformat
- Beberapa catatan dari halaman penuh dipindahkan ke halaman baru, sehingga menciptakan ruang kosong di halaman yang diperlukan
- Halaman baru ditautkan ke dalam struktur indeks
- Rekor baru disisipkan pada halaman yang diperlukan
Semua operasi ini menghasilkan catatan log, dan seperti yang Anda bayangkan, ini bisa jauh lebih banyak daripada yang diperlukan untuk menyisipkan catatan baru pada halaman yang tidak memerlukan pemisahan halaman. Kembali pada tahun 2009 saya membuat blog analisis biaya pemisahan halaman dalam hal log transaksi dan menemukan beberapa kasus di mana pemisahan halaman menghasilkan lebih dari 40 kali lebih banyak log transaksi daripada penyisipan biasa!
Langkah pertama dalam mengurangi biaya tambahan adalah menghapus indeks yang tidak digunakan, seperti yang saya jelaskan di atas, sehingga indeks tersebut tidak menghasilkan pemisahan halaman. Langkah kedua adalah mengidentifikasi indeks yang tersisa yang menjadi terfragmentasi (dan karenanya harus mengalami pemisahan halaman) menggunakan sys.dm_db_index_physical_stats
DMV (atau SQL Sentry Fragmentation Manager baru) dan secara proaktif membuat ruang kosong di dalamnya menggunakan faktor pengisi indeks. Fillfactor menginstruksikan SQL Server untuk meninggalkan ruang kosong pada halaman indeks saat indeks dibuat, dibangun kembali, atau ditata ulang sehingga ada ruang untuk memungkinkan catatan baru dimasukkan tanpa memerlukan pemisahan halaman, sehingga mengurangi catatan log tambahan yang dihasilkan.
Tentu saja tidak ada yang gratis – trade-off saat menggunakan fillfactors adalah Anda secara proaktif menyediakan ruang ekstra dalam indeks untuk mencegah lebih banyak catatan log yang dihasilkan – tapi itu biasanya trade-off yang baik untuk dilakukan. Memilih fillfactor relatif mudah dan saya membuat blog tentang itu di sini.
Ringkasan
Mengurangi latensi tulis dari file log transaksi tidak selalu berarti pindah ke subsistem I/O yang lebih cepat, atau memisahkan file ke dalam bagiannya sendiri dari subsistem I/O. Dengan beberapa analisis indeks sederhana dalam database Anda, Anda mungkin dapat secara signifikan mengurangi jumlah catatan log transaksi yang dihasilkan, yang mengarah pada pengurangan latensi tulis yang sepadan.
Ada masalah lain yang lebih halus yang dapat memengaruhi kinerja log transaksi, dan saya akan membahasnya di postingan mendatang.