Permintaan dan pembaruan sangat lambat setelah IndexOptimize

12

Database SQL Server 2017 Enterprise CU16 14.0.3076.1

Kami baru-baru ini mencoba beralih dari pekerjaan pemeliharaan Index Rebuild default ke Ola Hallengren IndexOptimize. Pekerjaan Rebuild Index default telah berjalan selama beberapa bulan tanpa masalah, dan pertanyaan dan pembaruan bekerja dengan waktu eksekusi yang dapat diterima. Setelah berjalan IndexOptimizedi database:

EXECUTE dbo.IndexOptimize
@Databases = 'USER_DATABASES',
@FragmentationLow = NULL,
@FragmentationMedium = 'INDEX_REORGANIZE,INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationHigh = 'INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationLevel1 = 5,
@FragmentationLevel2 = 30,
@UpdateStatistics = 'ALL',
@OnlyModifiedStatistics = 'Y'

kinerja sangat menurun. Pernyataan pembaruan yang mengambil 100 IndexOptimizems sebelum mengambil 78.000 ms sesudahnya (menggunakan rencana yang identik), dan kueri juga melakukan beberapa pesanan yang jauh lebih buruk.

Karena ini masih merupakan basis data pengujian (kami memigrasikan sistem produksi dari Oracle), kami kembali ke cadangan dan dinonaktifkan IndexOptimizedan semuanya kembali normal.

Namun, kami ingin memahami apa yang IndexOptimizeberbeda dari "normal" Index Rebuildyang dapat menyebabkan penurunan kinerja yang ekstrem ini untuk memastikan kami menghindarinya begitu kami mulai berproduksi. Setiap saran tentang apa yang harus dicari akan sangat dihargai.

Rencana eksekusi untuk pernyataan pembaruan saat lambat. yaitu
Setelah IndexOptimasi
rencana eksekusi Aktual (segera hadir)

Saya belum dapat menemukan perbedaan.
Rencanakan untuk permintaan yang sama ketika itu adalah rencana eksekusi yang cepat

Martin Bergström
sumber

Jawaban:

11

Saya menduga Anda memiliki tingkat sampel berbeda yang ditentukan antara dua pendekatan pemeliharaan Anda. Saya percaya skrip Ola menggunakan pengambilan sampel default kecuali jika Anda menentukan @StatisticsSampleparameternya , yang sepertinya tidak sedang Anda lakukan.

Pada titik ini, ini adalah spekulasi, tetapi Anda dapat memeriksa untuk melihat tingkat pengambilan sampel apa yang saat ini digunakan pada statistik Anda dengan menjalankan kueri berikut dalam database Anda:

SELECT  OBJECT_SCHEMA_NAME(st.object_id) + '.' + OBJECT_NAME(st.object_id) AS TableName
    ,   col.name AS ColumnName
    ,   st.name AS StatsName
    ,   sp.last_updated
    ,   sp.rows_sampled
    ,   sp.rows
    ,   (1.0*sp.rows_sampled)/(1.0*sp.rows) AS sample_pct
FROM sys.stats st 
    INNER JOIN sys.stats_columns st_col
        ON st.object_id = st_col.object_id
        AND st.stats_id = st_col.stats_id
    INNER JOIN sys.columns col
        ON st_col.object_id = col.object_id
        AND st_col.column_id = col.column_id
    CROSS APPLY sys.dm_db_stats_properties (st.object_id, st.stats_id) sp
ORDER BY 1, 2

Jika Anda melihat ini datang melalui 1s (misalnya 100%) kemungkinan ini adalah masalah Anda. Mungkin coba skrip Ola lagi termasuk @StatisticsSampleparameter dengan persentase yang dikembalikan oleh permintaan ini dan lihat apakah itu memperbaiki masalah Anda?


Sebagai bukti pendukung tambahan untuk teori ini, rencana eksekusi XML menunjukkan laju pengambilan sampel yang sangat berbeda untuk kueri lambat (2.18233%):

<StatisticsInfo LastUpdate="2019-09-01T01:07:46.04" ModificationCount="0" 
    SamplingPercent="2.18233" Statistics="[INDX_UPP_4]" Table="[UPPDRAG]" 
    Schema="[SVALA]" Database="[ulek-sva]" />

Lawan kueri cepat (100%):

<StatisticsInfo LastUpdate="2019-08-25T23:01:05.52" ModificationCount="555" 
    SamplingPercent="100" Statistics="[INDX_UPP_4]" Table="[UPPDRAG]" 
    Schema="[SVALA]" Database="[ulek-sva]" />
John Eisbrener
sumber
@JoshDarnell LOL, ini adalah kejadian kedua di mana Anda menemukan beberapa info statistik pendukung dalam paket kueri yang gagal saya lihat. Terima kasih atas hasil editnya!
John Eisbrener
Haha aku lupa itu kamu, John! Saya berjanji tidak akan menguntitmu 😅
Josh Darnell
@JoshDarnell Saya menghargai wawasan tambahan dan ini merupakan pengingat yang baik bahwa ada begitu banyak informasi dalam rencana eksekusi yang tidak boleh Anda lewatkan.
John Eisbrener
Senang untuk membantu! Dan ya, ada hal-hal yang saya lewatkan sepanjang waktu (saya dibakar oleh statistik, jadi saya cenderung pergi ke sana dengan cepat untuk melihat ada apa).
Josh Darnell
Terima kasih atas penjelasan ini, memang itulah masalahnya. Sebagian besar statistik memiliki tingkat sampel default sebesar 2,2% namun beberapa yang dibuat setelah migrasi dari Oracle memiliki tingkat sampel 100%. Tampaknya indeks default yang dibangun kembali menyimpan 100% tetapi ketika kami menggunakan IndexOptimize itu menerapkan default 2,2% untuk mereka juga. Menerapkan parameter @StatisticsSample dan menjalankan kueri lagi memverifikasi bahwa inilah yang menyebabkan masalah.
Martin Bergström
5

Jawaban John adalah solusi yang tepat, ini hanya merupakan tambahan untuk bagian mana dari rencana eksekusi yang diubah dan contoh tentang cara mudah menemukan perbedaan dengan Penjelajah Sentry One Plan

Pernyataan pembaruan yang mengambil 100 ms sebelum IndexOptimize mengambil 78.000 ms sesudahnya (menggunakan paket yang identik)

Saat melihat semua paket kueri saat kinerja Anda menurun, Anda dapat dengan mudah menemukan perbedaannya.

Performa yang menurun

masukkan deskripsi gambar di sini

Dua hitungan lebih dari 35 detik waktu cpu & waktu berlalu

Performa yang diharapkan

masukkan deskripsi gambar di sini

Jauh lebih baik

Degradasi utama adalah dua kali pada permintaan pembaruan ini:

UPDATE SVALA.INGÅENDEANALYS
                           SET 
                              UPPDRAGAVSLUTAT = @NEW$AVSLUTAT
                        WHERE INGÅENDEANALYS.ID IN 
                           (
                              SELECT IA.ID
                              FROM 
                                 SVALA.INGÅENDEANALYS  AS IA 
                                    JOIN SVALA.INGÅENDEANALYSX  AS IAX 
                                    ON IAX.INGÅENDEANALYS = IA.ID 
                                    JOIN SVALA.ANALYSMATERIAL  AS AM 
                                    ON AM.ID = IA.ANALYSMATERIALID 
                                    JOIN SVALA.ANALYSMATERIALX  AS AMX 
                                    ON AMX.ANALYSMATERIAL = AM.ID 
                                    JOIN SVALA.INSÄNTMATERIAL  AS IM 
                                    ON IM.ID = AM.INSÄNTMATERIALID 
                                    JOIN SVALA.INSÄNTMATERIALX  AS IMX 
                                    ON IMX.INSÄNTMATERIAL = IM.ID
                              WHERE IM.UPPDRAGSID = SVALA.PKGSVALA$STRIPVERSION(@NEW$ID)
                      )

rencana eksekusi untuk permintaan ini dengan kinerja yang menurun

Perkiraan rencana kueri dari kueri pembaruan ini memiliki perkiraan yang sangat tinggi ketika kinerja terdegradasi:

masukkan deskripsi gambar di sini

Sementara dalam kenyataannya (rencana eksekusi aktual) masih harus melakukan pekerjaan, hanya saja bukan jumlah gila yang ditampilkan perkiraan.

Dampak terbesar pada kinerja adalah dua pemindaian & hash match yang tergabung di bawah:

Pemindaian aktual pada kinerja terdegradasi # 1

masukkan deskripsi gambar di sini

Pemindaian aktual pada kinerja terdegradasi # 2

masukkan deskripsi gambar di sini


Paket eksekusi untuk permintaan ini dengan kinerja yang diharapkan

Saat Anda membandingkannya dengan perkiraan (atau aktual) dari rencana kueri dengan kinerja normal yang diharapkan, perbedaannya mudah dikenali.

masukkan deskripsi gambar di sini

Juga, dua akses tabel sebelumnya bahkan tidak terjadi:

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Anda tidak melihat penghapusan ini pada gabungan hash karena input build (atas) dimasukkan ke tabel hash terlebih dahulu. Setelah itu nilai nol diperiksa dalam tabel hash ini, mengembalikan nilai nol.

Randi Vertongen
sumber
1
Terima kasih atas uraian terperinci dari rencana tersebut, sangat membantu pemahaman saya tentang mengapa masalah terjadi. Saya pasti akan melihat Sentry One Plan Explorer, itu terlihat sangat berguna!
Martin Bergström
@ MartinBergström Sangat menyenangkan untuk mendengar, terima kasih telah memberikan rencana permintaan dan memberikan kami semua informasi yang relevan yang kami tanyakan dalam komentar :). Hal terbaik tentang penjelajah paket adalah gratis! Itu juga dapat bekerja dari dalam ssms (dengan mengklik kanan rencana eksekusi dan tekan "view with sentryone plan explorer").
Randi Vertongen
1

Tanpa informasi lebih lanjut, kami hanya dapat menerima bacokan informasi ringan dalam gelap, jadi Anda harus mengedit pertanyaan untuk memberikan sedikit lebih banyak. Misalnya, kueri merencanakan untuk pernyataan pembaruan yang telah Anda berikan waktunya, baik sebelum dan sesudah operasi pemeliharaan indeks karena rencana mungkin berbeda karena statistik indeks telah diperbarui ( https://www.brentozar.com/pastetheplan Saya berguna untuk ini, daripada mengisi pertanyaan dengan apa yang mungkin merupakan sebagian besar dari XML atau memberikan screen-grab yang tidak termasuk beberapa informasi terkait yang berisi teks dari paket tersebut).

Dua poin yang sangat sederhana dari kelelawar:

  1. Sudahkah proses optimalisasi selesai? Jika tes Anda bersaing dengan IO pembangunan kembali indeks berjalan lama yang akan mempengaruhi timing.
  2. Apakah Anda menguji beberapa kali? Jika pembaruan didasarkan pada data dari kueri yang mempertimbangkan banyak data (daripada `UPDATE TheTable SET yang sederhana, ThisColumn = 'Nilai Statis') maka mungkin data ini biasanya dalam memori tetapi telah dihapus dalam yang menjalankan kueri terkait yang pertama akan lebih lambat dari biasanya karena memukul disk daripada menemukan halaman yang diperlukan sudah ada di buffer pool dalam memori.
David Spillett
sumber
Terima kasih telah meluangkan waktu untuk membalas. Saya telah memperbarui pertanyaan dengan tautan pastetheplan. Optimalisasi telah menyelesaikannya berjalan sekitar 1 jam sehari sebelum masalah terjadi. Kami melakukan pengujian beberapa kali, dan itu sebenarnya mempengaruhi dua salinan dari database yang berjalan di dua lingkungan pengujian yang berbeda dengan cara yang sama. Pernyataan Pembaruan hanyalah contoh paling sederhana yang saya temukan, ada banyak sisipan dan pilihan lain yang terpengaruh
Martin Bergström
Dengan "berkali-kali" Saya bermaksud mencoba pembaruan beberapa kali setelah satu perubahan indeks, daripada menjalankan skrip pengoptimalan indeks beberapa kali secara independen (meskipun itu sendiri merupakan cara yang berguna untuk memverifikasi bahwa hasilnya dapat direproduksi). Jika pembilasan memori adalah (atau merupakan bagian dari) masalah maka pembaruan-dari-pilih pertama akan menjadi primadona buffer pool sehingga yang kemudian berpotensi lebih cepat karena IO berkurang secara signifikan.
David Spillett
Maaf jika jawaban saya tidak jelas. Ya, kami mencoba pembaruan beberapa kali. Perlambatan terjadi pada database yang digunakan oleh penguji untuk menguji aplikasi dan pertanyaan dan pembaruan di mana dijalankan beberapa kali sepanjang hari tanpa peningkatan kinerja.
Martin Bergström