Dalam posting terakhir saya, "Beberapa Paket untuk Kueri 'Identik'," saya berbicara tentang kasus di mana Anda mendapatkan dua paket berbeda untuk apa yang menurut Anda adalah kueri yang sama, serta kasus di mana Anda mendapatkan dua salinan dari sama rencanakan (dan bahkan mungkin tidak mengetahuinya). Seperti yang kami periksa di sana, "identik" bisa menjadi kata yang cukup kuat.
Skenario lain yang membuat orang mengulang adalah kasus di mana mereka memulihkan database ke server yang berbeda – misalnya, memulihkan database produksi ke server uji "identik" – dan mereka mendapatkan karakteristik kinerja yang berbeda atau rencana yang berbeda untuk kueri yang sama (tidak kutipan kali ini – saya benar-benar berbicara tentang pertanyaan yang benar-benar identik).
Apakah server benar-benar "identik"?
Orang-orang ini mungkin terlihat mirip, tapi tidak persis sama.Jika Anda menemukan skenario ini, hal pertama yang perlu Anda tanyakan pada diri sendiri adalah apakah kedua server ini benar-benar identik. Beberapa hal yang perlu diperiksa:
- Versi – Banyak pengoptimal dan perubahan perilaku kueri didorong melalui paket layanan dan pembaruan kumulatif. Seringkali saya melihat orang berkata, "Yah, mereka berdua tahun 2008!" – ketika, pada kenyataannya, satu adalah 2008 dan yang lainnya adalah 2008 R2, atau mereka berada di paket layanan yang berbeda atau bahkan tingkat pembaruan kumulatif. Karena banyak orang yang membaca @@VERSION salah mengartikan informasi paket layanan sistem operasi untuk informasi paket layanan SQL Server, saya akan mengatakan yang berikut ini lebih baik:
SELECT
SERVERPROPERTY
(N'ProductVersion'
);Saya tidak bisa cukup menekankan pentingnya menggunakan versi yang sama persis untuk melakukan tes apel-ke-apel yang sebenarnya. Jika Anda menggunakan SQL Server 2012 atau lebih baik, Anda dapat memeriksa posting build kami (SQL Server 2012 | SQL Server 2014) untuk menentukan paket layanan atau pembaruan kumulatif yang diperlukan untuk memastikan versi cocok.
- Edisi – Meskipun mudah-mudahan Anda menggunakan edisi yang sama di kedua server (atau yang setara, karena selain dari lisensi, Pengembang dan Evaluasi sama dengan Perusahaan), ketidakcocokan di sini dapat menyebabkan perilaku yang sangat berbeda. Misalnya, edisi yang berbeda memiliki kapasitas komputasi yang berbeda untuk berbagai fitur, dan kemudian ada hal-hal yang lebih halus seperti kemampuan untuk menggunakan tampilan yang diindeks tanpa petunjuk NOEXPAND atau melakukan perubahan skema atau pemeliharaan indeks secara online. Anda dapat membandingkan edisi menggunakan:
SELECT
SERVERPROPERTY
(N'Edition'
); - jumlah CPU – SQL Server pasti menggunakan jumlah penjadwal yang tersedia selama proses pembuatan rencana eksekusi, dan tidak dapat disangkal bahwa jumlah inti dapat mempengaruhi kinerja runtime yang sebenarnya (mari kita tinggalkan kecepatan clock, karena itu jarang menjadi faktor signifikan dalam kueri pertunjukan). Jangan hanya memvalidasi jumlah inti yang dipasang secara fisik di server yang mendasarinya, tetapi juga periksa log kesalahan SQL Server untuk mengetahui jumlah CPU yang sebenarnya dapat digunakan SQL Server karena lisensi. Bahkan melupakan jumlah inti mentah, pada sistem NUMA, pembatasan buatan di sini dapat menyebabkan profil kinerja yang sangat berbeda. Untuk informasi lebih lanjut, lihat posting terbaru Brent Ozar, "Mengapa Perizinan Berbasis Inti Penting untuk Penyetelan Kinerja." Edisi terikat di sini juga, karena di SQL Server 2012 dan 2014, Edisi Standar hanya dapat menggunakan 16 core tidak peduli apa pengaturan atau perangkat keras fisik Anda mungkin membuat Anda percaya. Pengaturan lain yang dapat memengaruhi pilihan dan kinerja paket berbasis CPU secara berbeda mencakup Gubernur Sumber Daya, MAXDOP seluruh server, afinitas CPU, dan ambang biaya untuk paralelisme.
- Jumlah memori – Seperti CPU, pengoptimal membuat pilihan paket berdasarkan jumlah memori yang tersedia. Dan seperti CPU, saya tidak hanya berbicara tentang jumlah RAM yang terpasang di sistem, tetapi jumlah memori yang diberikan ke SQL Server, dan berapa banyak yang benar-benar digunakan. Periksa pengaturan memori server maks, tetapi juga penghitung kinerja untuk memori total dan target, dan bahkan DBCC MEMORYSTATUS. Hal lain yang mungkin ingin Anda tinjau termasuk pengaturan Resource Governor dan Lock Pages in Memory. Ada juga pengaturan yang, jika berbeda antara dua server, dapat memiliki pengaruh yang signifikan pada seberapa banyak cache paket yang digunakan untuk kumpulan kueri yang sama:optimalkan untuk beban kerja ad hoc. Kimberly Tripp memiliki posting yang bagus tentang ini:Rencanakan cache dan optimalkan untuk beban kerja adhoc. Terakhir, jika servernya virtual, ketahuilah bahwa lingkungan dapat berperan di sini – terutama ketika pengaturan memori VM tidak sesuai dengan produksi atau bersifat dinamis.
- Kolam buffer / cache paket – Saat Anda memulihkan database di server pengujian, ada banyak hal yang tidak langsung siap untuk Anda. Kumpulan buffer tidak berisi data apa pun yang mungkin telah ada di server sumber – jadi akan ada I/O tambahan yang diperlukan untuk memasukkan data ke dalam memori saat pertama kali ditanyakan. Dan jika kumpulan buffer dibatasi secara berbeda dari produksi karena beberapa faktor di atas, mungkin tidak mungkin untuk mencapai pola kinerja yang sama bahkan setelah menjalankan kueri beberapa kali – Paul White (@SQL_Kiwi) membicarakan hal ini dalam jawabannya di Administrator Basis Data. Selain itu, cache paket tidak akan berisi paket apa pun yang ada dalam produksi, jadi setidaknya – bahkan jika paket yang sama akhirnya dikompilasi (yang mungkin tidak terjadi karena parameter yang berbeda dari saat paket dikompilasi pada aslinya server) – Anda akan dikenakan biaya kompilasi tambahan. Dan itu dapat berubah jika Anda juga memiliki tanda jejak yang memengaruhi rencana.
- Subsistem disk – Sementara kecepatan dan ukuran disk yang digunakan tidak akan secara langsung memengaruhi pilihan paket, mereka tentu saja dapat memengaruhi kinerja yang diamati, yang dapat membuat Anda bertanya-tanya mengapa kueri yang sama, dengan paket yang sama, berjalan jauh lebih cepat pada satu sistem daripada yang lain. I/O biasanya merupakan hambatan terbesar SQL Server, dan sangat jarang bahwa server uji benar-benar memiliki subsistem dasar yang sama persis dengan produksinya yang setara. Jadi, jika Anda melihat perbedaan kinerja antara kedua sistem, dan paket serta elemen perangkat keras lainnya sama, ini mungkin tempat terbaik berikutnya untuk memeriksanya. Dan jangan lupa bahwa, mulai SQL Server 2014, Resource Governor mungkin membatasi kinerja I/O Anda.
- Tandai bendera – Periksa daftar bendera jejak global yang ditetapkan di kedua server; ada beberapa yang dapat memengaruhi pengoptimalan, perilaku rencana, dan kinerja yang dirasakan, meskipun semua setelan di atas identik. Berikut adalah 10 yang umum dan terkenal (meskipun ini sama sekali bukan dukungan untuk mengaktifkan semua ini tanpa pengujian regresi menyeluruh):
Tandai Penjelasan 2301 Memaksa pengoptimal untuk menghabiskan lebih banyak waktu mencoba menemukan rencana yang optimal. 2312 Memaksa estimator kardinalitas baru SQL Server 2014. 2335 Menyebabkan pemberian memori yang lebih konservatif. 2453 Memaksa OPTION (RECOMPILE) untuk kueri yang merujuk variabel tabel. 2861 Memungkinkan SQL Server untuk men-cache paket sepele / tanpa biaya. 4136 Secara efektif, tambahkan OPTIMIZE FOR UNKNOWN ke semua kueri (untuk menggagalkan sniffing parameter). 4199 Payung yang berisi banyak perbaikan pengoptimal. 8744 Menonaktifkan pengambilan awal untuk loop bersarang. 9481 Menonaktifkan penaksir kardinalitas baru SQL Server 2014.
Daftar tanda jejak itu sama sekali tidak lengkap; ada banyak lainnya, termasuk yang tidak berdokumen, saya diminta untuk tidak menyebutkannya. Jika Anda menggunakan orang lain yang tidak tercantum di atas (dan tidak dapat menjelaskan alasannya), Anda mungkin menemukan petunjuk di KB #920093, KB #2964518, Trace Flags (MSDN) atau Trace Flags di SQL Server (TechNet). Anda juga akan menemukan beberapa wawasan berharga dalam berbagai posting oleh Paul White, baik di sini, atau di sql.kiwi. - Konkurensi – Agaknya sistem pengujian digunakan untuk hal-hal selain apa pun yang sedang Anda uji. Dan kecuali Anda melakukan semacam replay, itu juga kemungkinan memiliki profil beban kerja yang sangat berbeda. Perbedaan beban kerja ini jelas dapat berdampak langsung pada ketersediaan sumber daya untuk melayani permintaan yang Anda uji, dan pada gilirannya persepsi kinerja permintaan tersebut. Jangan lupa untuk memeriksa layanan lain yang mungkin tidak ada dalam produksi, atau ada tetapi digunakan dengan cara yang berbeda (seperti Layanan Analisis, Layanan Pelaporan, layanan Windows, dan bahkan aplikasi Anda sendiri). Sebaliknya, mungkin ada layanan seperti ini dalam produksi yang memengaruhi kinerja di sana, atau overhead tambahan pada instans itu sendiri yang tidak ditiru dalam pengujian:selain dari beban kerja produksi aktual, pikirkan hal-hal seperti pelacakan, peristiwa yang diperpanjang, pemantauan berdampak tinggi, ubah pelacakan, ubah pengambilan data, audit, pialang layanan, pemeliharaan indeks, tugas pencadangan, pemeriksaan DBCC, pencerminan, replikasi, grup ketersediaan, dan daftarnya terus bertambah…
Apakah databasenya masih "identik"?
Dengan asumsi semua variabel perangkat keras dan beban kerja cukup cocok, masih sulit untuk memastikan bahwa database tetap sama. Jika Anda melakukan pencadangan/pemulihan ke sistem pengujian, basis data baru dimulai sama persis dengan sumbernya (kecuali untuk lokasi fisik dan keamanan). Tetapi segera setelah Anda mulai menyentuhnya dengan cara apa pun, itu sangat cepat menyimpang dari salinan produksi, karena Anda dapat melakukan salah satu atau semua hal berikut:
- Ubah data, skema, atau keduanya.
- Secara tidak sengaja memulai pembaruan statistik secara otomatis.
- Menambahkan, mendefrag, atau membangun kembali indeks secara manual, atau membuat atau memperbarui statistik.
- Ubah pengaturan database seperti tingkat kompatibilitas, tingkat isolasi, parameterisasi paksa, indeks XML selektif, atau salah satu opsi bernama "Otomatis"-
. (Heck, bahkan data dan lokasi file log dan setelan pertumbuhan dapat memengaruhi kinerja kueri, dan ini termasuk tempdb.) - Kosongkan cache paket, kumpulan buffer, atau keduanya, secara langsung atau sebagai efek samping dari peristiwa lain (seperti RECONFIGURE atau restart layanan).
Selain itu, setelah Anda mulai membuat rencana kueri baru, bahkan sebelum perubahan di atas terjadi, Anda harus ingat bahwa perubahan tersebut mungkin didasarkan pada data yang berbeda dari data yang digunakan untuk membuat rencana untuk kueri yang sama dalam produksi. Sebagai contoh, kardinalitas saat rencana dikompilasi dalam produksi dapat menyimpang secara signifikan antara titik tersebut dan waktu pencadangan, yang berarti rencana baru akan dibuat berdasarkan statistik dan informasi histogram yang berbeda.
Hal-hal ini menyimpang lebih jauh jika ini sebenarnya bukan pemulihan baru-baru ini – melainkan dua skema dan kumpulan data yang Anda tetap sinkronkan dengan cara lain (seperti penerapan skema dan/atau perubahan data secara manual, atau bahkan replikasi). Karena keterbatasan ruang disk, Anda mungkin juga hanya mengambil sebagian dari data produksi, atau bahkan klon khusus statistik – perbedaan data ini hampir pasti akan menghasilkan karakteristik kinerja yang berbeda untuk semua kecuali kueri yang paling sederhana, bahkan jika Anda melakukannya semoga beruntung dan dapatkan rencana yang sama untuk beberapa orang.
Apakah kueri benar-benar "identik"?
Bahkan jika semua yang di atas diperiksa, masih ada skenario di mana Anda mendapatkan paket yang berbeda karena pengaturan sesi (Anda mungkin menggunakan salinan SSMS yang berbeda, dengan pengaturan yang berbeda, atau alat klien yang berbeda sama sekali), atau skema default yang berbeda ( Anda mungkin terhubung ke server pengujian sebagai login auth Windows atau SQL yang berbeda, misalnya). Saya berbicara banyak tentang hal-hal ini di posting saya sebelumnya.
Kesimpulan
Meskipun ada cara untuk mengurangi beberapa perbedaan (lihat DBCC OPTIMIZER_WHATIF untuk membodohi server pengujian Anda agar mempercayai hal-hal fenomenal tentang perangkat keras yang mendasarinya), kenyataannya akan sangat menantang untuk membuat dua server berkinerja andal dan konsisten identik, dan bahwa ada kemungkinan lusinan alasan mengapa Anda mungkin mendapatkan paket yang berbeda atau kinerja yang berbeda pada dua server yang serupa (atau bahkan identik).
Apakah Anda memiliki trik tertentu? Apakah Anda memiliki poin rasa sakit yang menyiksa dengan ide-ide di atas (atau orang lain yang tidak saya sebutkan)? Silakan bagikan di komentar di bawah!