Bagaimana cara menurunkan HEAP Fragmentasi di SQL Server?

10

Saya baru-baru menemukan bahwa satu meja tumpukan memiliki lebih dari 70% fragmentasi. Jadi saya memutuskan untuk melakukan

ALTER TABLE dbo.myTable REBUILD

Cukup lucu, setelah itu saya mengalami fragmentasi 20%. Tidak ada tulisan di meja itu sejak itu. Jadi saya memutuskan untuk melakukan pembangunan kembali.

Setelah ke-2 kalinya, table hat 50% fragmentasi bahkan lebih! Saya benar-benar tidak mengerti bagaimana ini bisa terjadi ...

tuxmania
sumber
Apa yang Anda maksud ketika mengatakan fragmentasi logis. Ini adalah fragmentasi dalam hal penggunaan halaman data. Saya tahu tidak ada pesanan tetapi data yang tidak diurutkan tidak terfragmentasi per se. Fragmentasi dalam hal ini berarti penggunaan halaman data secara efisien.
tuxmania
2
Saya kira kita harus bertanya, seberapa besar tabelnya? Dalam baris dan halaman.
Cody Konior

Jawaban:

17

Apa Arti Fragmentasi Berarti dalam Tumpukan

Nilai fragmentasi dalam Heap yang Anda dapatkan dari kolom avg_fragmentation_in_percentdengan meminta sys.dm_db_index_physical_statsDMV menyatakan itu

Fragmentasi logis untuk indeks, atau perluasan fragmentasi untuk tumpukan di unit alokasi IN_ROW_DATA.

Lebih jauh BOL yang sama mengatakan itu

Ini adalah persentase luasan tidak beraturan di halaman daun tumpukan. Tingkat out-of-order adalah satu di mana tingkat yang berisi halaman saat ini untuk tumpukan tidak secara fisik tingkat berikutnya setelah tingkat yang berisi halaman sebelumnya.

Jadi Anda dapat melihat itu bukan ruang kosong yang ada di halaman yang dialokasikan untuk Heap tetapi urutan beragam halaman yang menciptakan fragmentasi.

Ini dapat ditunjukkan dengan uji kecil. Mari kita buat Heap Table dan masukkan beberapa record di dalamnya lalu periksa fragmentasi.

create table dbo.HeapTest
(
Id INT not NULL Default (1),
Col1   char(5000) Not null Default ('Heaps Are Cool')
)

SET NOCOUNT ON

Insert into dbo.Heaptest default values
go 50

select index_type_desc,avg_fragmentation_in_percent,fragment_count,
avg_page_space_used_in_percent,record_count
from sys.dm_db_index_physical_stats(db_id(),object_id('dbo.HeapTest','U'),0,default,'detailed')

Jadi tabel Heap dibuat dengan 50 catatan di dalamnya. Di bawah ini adalah apa yang tampak seperti fragmentasi setelah permintaan statistik DMV sys.dm_db_index_physical

masukkan deskripsi gambar di sini

Anda dapat melihat avg_fragmentation_in_percentnilai kolom adalah 33%. Sekarang mari kita lihat bagaimana mengatur halaman. Ini dapat dilakukan dengan menggunakan permintaan tidak berdokumen%%lockres%% . Kueri akan menjadi

SELECT  %%lockres%%, * FROM dbo.HeapTest;

Dan di bawah ini adalah seperti apa output itu. Melampirkan hanya bagian yang relevan saja. Kueri menghasilkan 50 baris karena kami memasukkan 50 baris dalam tabel dbo.HeapTest kami.

masukkan deskripsi gambar di sini

Apa yang dikatakannya adalah halaman pertama memiliki ID 197, halaman berikutnya memiliki ID 242halaman berikutnya memiliki ID terus menerus sampai kita mencapai ID halaman 264karena setelah itu kita mendapatkan ID halaman 280. Jadi lompatan nomor ID halaman inilah yang sebenarnya menyebabkan fragmentasi.

Sekarang jangan sampai membangun kembali heap dan jalankan Perintah lagi untuk melihat fragmentasi dan bagaimana halaman diatur. Kami mendapatkan fragmentasi seperti

masukkan deskripsi gambar di sini

Anda dapat melihat fragmentasi sekarang 14%.

Mari kita lihat nomor halaman yang dialokasikan

masukkan deskripsi gambar di sini

Kami hanya memiliki satu lompatan istirahat semua halaman dialokasikan ID halaman secara seri. Karena hanya satu lompatan fragmentasi menurun secara signifikan.

Saya membangun kembali Heap lagi dan sekarang ketika saya memeriksa fragmentasi itu benar-benar hilang. Dan alokasi ID halaman seperti

masukkan deskripsi gambar di sini

Mengapa Fragmentasi Meningkat

Sekarang mengenai apa yang bisa menyebabkan fragmentasi naik, kita bisa membenarkannya bahwa ketika halaman dialokasikan ke heap, mereka tidak akan berlanjut, seperti yang Anda lihat di atas apa yang menyebabkan nilai fragmentasi meningkat adalah lompatan dalam ID PAGE yang dialokasikan untuk halaman.

Di bagian belakang kepala Anda juga harus ingat bahwa kata fragmentasi untuk HEAP tidak memiliki arti, bagaimana Anda mendefinisikan fragmentasi untuk sekelompok halaman yang tidak dipesan.

Sangat Khawatir tentang Fragmentasi

Jika Anda benar-benar menghadapi skenario di mana tabel tumpukan terfragmentasi dan memperlambat kueri, akan lebih baik membuat indeks berkerumun di atas meja daripada membangunnya kembali. Alasannya adalah ketika Anda membangun kembali menimbun semua indeks Non Cluster yang mendasarinya juga dibangun kembali menyebabkan proses pembangunan kembali memakan waktu lebih lama, memanfaatkan banyak sumber daya dan membengkak log transaksi. Pada sistem produksi kita selalu berusaha menghindari ini. Paulus membahas hal ini di Bagian Mitos tentang tumpukan .

PS: Tolong jangan gunakan perintah tidak berdokumen pada sistem produksi. Ini hanya untuk demonstrasi.

Shanky
sumber
Terima kasih atas analisis terperinci Anda. Saya menghadapi tabel tumpukan besar karena beberapa penggemar data vault berpikir ini jauh lebih baik daripada menggunakan Indeks Clustered tetapi kemudian mereka menggunakan banyak kendala pemeriksaan dan indeks non-cluster pada tumpukan itu jadi saya tidak benar-benar melihat manfaat dari tumpukan di situasi ini. Namun karena saya hanya pengembang bodoh saya harus berurusan dengan ini. Terima kasih sekali lagi untuk wawasannya :)
tuxmania
Bagaimana Anda menjalankan select index_type_desc, avg_fragmentation_in_percent, fragment_count, avg_page_space_used_in_percent, record_count dari sys.dm_db_index_physical_stats (db_id (), object_id (), objek_id ('dbo.heaptest,' hanya untuk hasil, karena ', langsung saja, karena', langsung saja, karena ', langsung saja, karena' satu meja ? itu mengembalikan semua indeks pada semua tabel untuk saya bahkan jika saya benar menentukan nama tabel saya di 'object_id'
Mickael
@Mickael Saya telah menggunakan fungsi db_id () yang akan mengambil database saat ini dan saya telah secara khusus memberikan nama objek sehingga ini akan selalu melihat ke dalam database saat ini dan mencari Heaptestdan memberikan hasilnya. Saya yakin Anda mungkin melewatkan sesuatu. Pastikan saja tingkat kompatibilitasnya tidak 80 dalam hal ini fungsi db_id tidak berfungsi
Shanky
@Shanky mengapa Anda tidak merekomendasikan untuk menggunakan query %% lockres %% yang tidak didokumentasikan dalam produksi? Bisakah Anda menjelaskannya secara detail?
Ralph
@ user1624552 Hanya karena tidak berdokumen, berarti MS juga tidak menyimpan dokumentasi tentang hal itu diperbarui. Apa efek setelahnya bagaimana cara kerjanya tidak didokumentasikan di mana pun itu sebabnya ia diminta demikian. Mis ada perintah fn_dump_dblog () yang membuat scheduler tersembunyi dan itu tidak bagus. Perintah ini juga tidak didukung. Anda dapat menggunakannya tetapi risikonya ada pada Anda.
Shanky