Meningkatkan kecepatan membangun kembali indeks pada SQL server

9

Saya mengimpor sejumlah besar data ke database kosong, dan sebelum saya mulai, saya menonaktifkan semua indeks non-cluster non-unik untuk melihat apakah saya dapat meningkatkan kinerja impor.

Sekarang saya ingin mengaktifkan kembali indeks, dan saya bertanya-tanya apakah ada yang bisa saya lakukan untuk mengoptimalkan ini.

Ada> 100 tabel dan hampir 2.000 indeks yang akan dibangun kembali. Basis data berukuran 200GB.

Bagian kunci dari skrip yang saya jalankan adalah ini:

declare c_toggle_index cursor FORWARD_ONLY READ_ONLY for
    select  'alter index ' + QUOTENAME(i.name) + ' on ' + o.name + ' rebuild'
    from    sys.indexes as i
    Inner Join sys.objects o
    On o.object_id = i.object_id
    Where o.is_ms_shipped = 0
    And i.index_id >= 1
    and i.type > 1
    and i.is_disabled = 1

Saya mempertimbangkan pengaturan ONLINE = OFF untuk pernyataan indeks alter, tetapi ketika indeks mulai dinonaktifkan, saya tidak yakin bahwa pengaturan ini akan berpengaruh. Saya juga mempertimbangkan pengaturan SORT_IN_TEMPDB = ON, tetapi karena file tempdb berada di drive yang sama dengan file .mdf dari database, saya berasumsi bahwa tidak ada manfaat untuk melakukan itu.

Saat menjalankan skrip pembangunan kembali, saya perhatikan bahwa saya memiliki banyak jenis menunggu CXPACKET. Saya tidak benar-benar mengerti mengapa itu terjadi atau jika itu masalah yang harus saya cari untuk diatasi.

Satu poin terakhir yang mungkin relevan: seluruh server saya saat ini tidak aktif selain dari impor data ke dalam database. Tidak ada aktivitas pengguna lain untuk dipertimbangkan atau dikhawatirkan; Satu-satunya kekhawatiran saya adalah mengimpor data ke dalam database dalam waktu sesingkat mungkin.

paH
sumber
3
Ketika Anda mengatakan bahwa satu-satunya masalah Anda adalah waktu impor, apakah maksud Anda waktu dari awal impor hingga akhir mengaktifkan kembali indeks? Jika demikian, Anda harus membiarkan saja indeks diaktifkan selama impor. 2.000 indeks untuk data 200GB terdengar seperti banyak indeks bagi saya. Mungkin Anda harus melihat indeks penggunaan DMV untuk melihat apakah ada beberapa yang bisa dihapus.
Max Vernon
1
Hanya untuk memperjelas, Anda perlu melakukan impor 200GB yang sama berulang kali, dan bukan hanya sekali?
Jon Seigel
1
Saya hanya perlu melakukan impor sekali tetapi sebagai bagian dari proses yang lebih besar dengan rentang waktu yang terbatas, jadi saya saat ini sedang menguji proses itu agar sesuai dengan jendela tersebut. @ MaxVernon Sepertinya Anda benar bahwa membiarkan indeks diaktifkan adalah cara tercepat, meskipun saya terkejut ketika saya membaca bahwa biasanya lebih cepat untuk menonaktifkan indeks, mengimpor data, lalu mengaktifkan kembali indeks. Ini adalah database pihak ketiga sehingga menghapus indeks atau mengubahnya tidak benar-benar mungkin.
paulH
3
Baik. Tentang CXPACKETmenunggu: indeks membangun kembali sendiri indeks pemindaian (bahkan indeks sedang dibangun kembali ), dan pemindaian tersebut dapat menggunakan paralelisme. Anda tidak perlu khawatir tentang menunggu itu - paralelisme mungkin membantu.
Jon Seigel

Jawaban:

10

Mencapai kinerja impor yang optimal dalam skenario ini membutuhkan tiga hal:

  1. Sisipan tabel dasar yang dicatat minimal
  2. Membangun indeks nonclustered minimal dicatat
  3. Menghindari pembacaan fisik

Penebangan Minimal

Mencapai insersi minimal-login ke tabel clustered kosong tanpa indeks nonclustered membutuhkan:

  1. Menggunakan model pemulihan basis data SIMPLEatauBULK_LOGGED
  2. Menentukan kunci meja dan input yang dipesan (mis. TABLOCKDan ORDERpetunjuk)

Catatan:

Dimungkinkan juga untuk mencapai sisipan minimal-log ke tabel berkerumun yang memiliki indeks nonclustered asalkan flag jejak 610 diaktifkan. Apakah sisipan indeks yang tidak tercakup dicatat minimal atau tidak tergantung pada rencana kueri yang dipilih oleh pengoptimal kueri.

Jika rencana kueri menggunakan iterator terpisah untuk indeks yang tidak dikelompokkan, dan iterator memiliki DMLRequestSortproperti yang disetel true, sisipan indeks yang tidak dikelompokkan akan dicatat secara minimal, asalkan kondisi lain yang disebutkan sebelumnya dipenuhi.

Membangun indeks yang tidak tercakup secara terpisah

Keuntungan melakukan ini adalah:

  1. Sisipan indeks yang dikelompokkan dapat secara minimal dicatat tanpa mengaktifkan TF 610
  2. CREATE INDEX dicatat minimal jika model pemulihan tidak FULL

Menghindari pembacaan fisik

Idealnya, data yang akan diimpor akan disimpan pada mesin terpisah, atau setidaknya pada penyimpanan fisik terpisah dari yang digunakan untuk meng-host database.

Server database harus memiliki cukup memori untuk menampung tabel basis terbesar dalam cache, dengan sisa yang cukup untuk operasi penyortiran yang diperlukan ketika membangun indeks yang tidak tercakup.

Pola yang baik adalah memuat tabel dasar dengan cepat (memuat indeks berkerumun minimal) dan kemudian membangun semua indeks yang tidak dikelompokkan untuk tabel itu sementara halaman datanya masih di-cache.

Pertanyaannya menguraikan proses di mana tabel dasar dimuat pertama, dan kemudian indeks nonclustered dibangun. Definisi kursor tidak menggunakan ORDER BYklausa untuk setidaknya grup indeks nonclustered dibangun di atas tabel yang sama bersamaan.

Hasil yang mungkin adalah bahwa halaman data untuk tabel yang berbeda berulang kali dibaca ke dalam cache dan kemudian dibuang karena indeks yang tidak tercakup dibuat dalam urutan non-deterministik.

Biaya pembacaan fisik berulang sepenuhnya mendominasi manfaat dari penebangan minimal yang diperoleh dengan membangun indeks nonclustered secara terpisah. Ini menjelaskan mengapa Anda menemukan bahwa memuat tabel dengan indeks yang ada lebih cepat (karena semua indeks nonclustered untuk tabel tertentu dipertahankan sebelum pindah ke tabel berikutnya).

Ringkasan

Proses impor harus dikerjakan ulang untuk memuat sekaligus satu tabel sekaligus. Ini berarti memuat tabel dan membangun semua indeks yang tidak dikelompokkan sebelum pindah ke yang berikutnya. Contoh SQL Server harus memiliki cukup memori yang tersedia untuk menampung tabel terbesar dan melakukan pengurutan indeks nonclustered terbesar pada saat yang sama.

Anda juga dapat mencoba mengaktifkan TF 610 sebelum memuat data ke dalam tabel dengan indeks nonclustered yang sudah ada. Ini biasanya tidak secepat metode sebelumnya, tetapi mungkin cukup cepat.

Lihat yang berikut untuk informasi lebih lanjut:

Panduan Kinerja Pemuatan Data

Operasi yang Dapat Dicatat Minimal

Paul White 9
sumber