Dapatkah tabel sistem SQL Server didefragmentasi?

15

Kami memiliki beberapa database tempat sejumlah besar tabel dibuat dan dihapus. Dari apa yang dapat kami katakan, SQL Server tidak melakukan pemeliharaan internal pada tabel basis sistem , yang berarti bahwa mereka dapat menjadi sangat terfragmentasi dari waktu ke waktu dan ukurannya membengkak. Ini memberikan tekanan yang tidak perlu pada kumpulan buffer dan juga berdampak negatif pada kinerja operasi seperti menghitung ukuran semua tabel dalam database.

Adakah yang punya saran untuk meminimalkan fragmentasi pada tabel internal inti ini? Satu solusi yang jelas bisa untuk menghindari membuat begitu banyak tabel (atau untuk membuat semua tabel sementara di tempdb), tetapi untuk tujuan pertanyaan ini, katakanlah bahwa aplikasi tidak memiliki fleksibilitas itu.

Sunting: Penelitian lebih lanjut menunjukkan pertanyaan yang tidak terjawab ini , yang terlihat terkait erat dan menunjukkan bahwa beberapa bentuk pemeliharaan manual ALTER INDEX...REORGANIZEdapat menjadi pilihan.


Penelitian awal

Metadata tentang tabel ini dapat dilihat di sys.dm_db_partition_stats:

-- The system base table that contains one row for every column in the system
SELECT row_count,
    (reserved_page_count * 8 * 1024.0) / row_count AS bytes_per_row, 
    reserved_page_count/128. AS space_mb
FROM sys.dm_db_partition_stats
WHERE object_id = OBJECT_ID('sys.syscolpars')
    AND index_id = 1
-- row_count:       15,600,859
-- bytes_per_row:   278.08
-- space_mb:        4,136

Namun, sys.dm_db_index_physical_statstampaknya tidak mendukung tampilan fragmentasi tabel ini:

-- No fragmentation data is returned by sys.dm_db_index_physical_stats
SELECT *
FROM sys.dm_db_index_physical_stats(
    DB_ID(),
    OBJECT_ID('sys.syscolpars'),
    NULL,
    NULL,
    'DETAILED'
)

Script Ola Hallengren juga mengandung parameter untuk mempertimbangkan defragmentasi untuk is_ms_shipped = 1objek, tetapi prosedur ini secara diam-diam mengabaikan tabel basis sistem bahkan dengan parameter ini diaktifkan. Ola mengklarifikasi bahwa ini adalah perilaku yang diharapkan; hanya tabel pengguna (bukan tabel sistem) yang ms_shipped (mis. msdb.dbo.backupset) yang dipertimbangkan.

-- Returns code 0 (successful), but does not do any work for system base tables.
-- Instead of the expected commands to update statistics and reorganize indexes,
-- no commands are generated. The script seems to assume the target tables will
-- appear in sys.tables, but this does not appear to be a valid assumption for
-- system tables like sys.sysrowsets or sys.syscolpars.
DECLARE @result int;
EXEC @result = IndexOptimize @Databases = 'Test',
        @FragmentationLow = 'INDEX_REORGANIZE',
        @FragmentationMedium = 'INDEX_REORGANIZE',
        @FragmentationHigh = 'INDEX_REORGANIZE',
        @PageCountLevel = 0,
        @UpdateStatistics = 'ALL',
        @Indexes = '%Test.sys.sysrowsets.%',
        -- Proc works properly if targeting a non-system table instead
        --@Indexes = '%Test.dbo.Numbers.%',
        @MSShippedObjects = 'Y',
        @Execute = 'N';
PRINT(@result);


Info tambahan yang diminta

Saya menggunakan adaptasi dari permintaan Harun di bawah penggunaan tabel penyangga tabel sistem memeriksa, dan ini menemukan bahwa ada puluhan GB tabel sistem di kolam penyangga hanya untuk satu database, dengan ~ 80% dari ruang itu menjadi ruang bebas dalam beberapa kasus .

-- Compute buffer pool usage by system table
SELECT OBJECT_NAME(p.object_id),
    COUNT(b.page_id) pages,
    SUM(b.free_space_in_bytes/8192.0) free_pages
FROM sys.dm_os_buffer_descriptors b
JOIN sys.allocation_units a
    ON a.allocation_unit_id = b.allocation_unit_id
JOIN sys.partitions p
    ON p.partition_id = a.container_id
    AND p.object_id < 1000 -- A loose proxy for system tables
WHERE b.database_id = DB_ID()
GROUP BY p.object_id
ORDER BY pages DESC

masukkan deskripsi gambar di sini

Geoff Patterson
sumber

Jawaban:

11

Apakah Anda yakin telah secara positif dan akurat mengidentifikasi tabel sistem ini sebagai satu-satunya sumber "tekanan yang tidak perlu pada kumpulan buffer dan juga berdampak negatif pada kinerja operasi seperti menghitung ukuran semua tabel dalam database"? Apakah Anda yakin tabel sistem ini tidak dikelola sendiri sedemikian rupa sehingga (a) fragmentasi diminimalkan atau disimpan di cek secara diam-diam atau hanya (b) dikelola secara efisien dalam memori sehingga tingkat defragmentasi benar-benar tidak memengaruhi banyak hal?

Anda dapat melihat berapa banyak halaman sedang digunakan, dan Anda dapat melihat berapa banyak ruang bebas pada halaman yang berada di memori ( page_free_space_percentselalu NULLdalam alokasi DMF, tapi ini adalah tersedia dari buffer DMV) - ini akan memberi Anda beberapa ide jika apa yang Anda khawatirkan benar-benar sesuatu yang Anda harus khawatirkan:

SELECT 
  Number_of_Pages = COUNT(*), 
  Number_of_Pages_In_Memory = COUNT(b.page_id),
  Avg_Free_Space = AVG(b.free_space_in_bytes/8192.0) 
FROM sys.dm_db_database_page_allocations
(
  DB_ID(),
  OBJECT_ID(N'sys.syscolpars'),
  NULL,NULL,'DETAILED'
) AS p
LEFT OUTER JOIN sys.dm_os_buffer_descriptors AS b
ON b.database_id = DB_ID() 
AND b.page_id = p.allocated_page_page_id 
AND b.file_id = p.allocated_page_file_id;

Jika jumlah halaman Anda kecil (seperti mungkin <10.000 untuk tabel sistem) atau jika ruang kosong "rendah" (tidak yakin apa ambang batas khas Anda untuk reorg / dibangun kembali), fokuslah pada buah lain yang lebih menarik dan menggantung rendah. .

Jika jumlah halaman Anda besar dan ruang kosong "tinggi", ok, maka mungkin saya memberikan kredit terlalu banyak untuk SQL Server. Seperti yang Anda tunjukkan dari pertanyaan lain , ini berfungsi ...

ALTER INDEX ALL ON sys.syscolpars REORGANIZE;

... dan tidak mengurangi fragmentasi. Meskipun mungkin memerlukan izin tinggi (saya tidak mencoba sebagai prajurit infanteri).

Mungkin Anda bisa melakukan ini secara berkala sebagai bagian dari perawatan Anda sendiri, jika itu membuat Anda merasa baik dan / atau Anda memiliki bukti bahwa itu memiliki dampak positif pada sistem Anda sama sekali.

Aaron Bertrand
sumber
Saya menambahkan jawaban lain yang merangkum apa yang akhirnya kami lakukan, dan kemudian membersihkan komentar sebelumnya di sini. Sekali lagi terima kasih atas bantuan Anda!
Geoff Patterson
7

Berdasarkan petunjuk dari jawaban Harun serta penelitian tambahan, berikut adalah tulisan singkat dari pendekatan yang saya ambil.

Dari apa yang bisa saya katakan, opsi untuk memeriksa fragmentasi tabel basis sistem terbatas. Saya pergi ke depan dan mengajukan masalah Connect untuk memberikan visibilitas yang lebih baik, tetapi sementara itu tampaknya bahwa opsi mencakup hal-hal seperti memeriksa kumpulan buffer atau memeriksa rata-rata # byte per baris.

Saya kemudian membuat prosedur untuk melakukan `ALTER INDEX ... REORGANIZE pada semua tabel basis sistem . Menjalankan prosedur ini pada beberapa server dev kami yang paling banyak digunakan (ab) menunjukkan bahwa ukuran kumulatif tabel basis sistem dipangkas hingga 50GB (dengan ~ 5MM tabel pengguna pada sistem, jadi jelas merupakan kasus ekstrem).

Salah satu tugas pemeliharaan malam kami, yang membantu membersihkan banyak tabel pengguna yang dibuat oleh berbagai unit test dan pengembangan, sebelumnya membutuhkan waktu ~ 50 menit untuk diselesaikan. Kombinasi sp_whoisactive, sys.dm_os_waiting_tasksdanDBCC PAGE menunjukkan bahwa menunggu didominasi oleh I / O pada tabel dasar sistem.

Setelah reorganisasi semua tabel basis sistem, tugas pemeliharaan turun menjadi ~ 15 menit. Masih ada beberapa I / O yang menunggu, tetapi mereka secara signifikan berkurang, mungkin karena lebih banyak data yang tersisa dalam cache dan / atau lebih readaheads karena fragmentasi yang lebih rendah.

Oleh karena itu, kesimpulan saya adalah bahwa menambahkan ALTER INDEX...REORGANIZEtabel basis sistem ke dalam rencana pemeliharaan mungkin merupakan hal yang berguna untuk dipertimbangkan, tetapi kemungkinan hanya jika Anda memiliki skenario di mana sejumlah objek yang tidak biasa sedang dibuat pada database.

Geoff Patterson
sumber
Memberi +1 untuk pertanyaan dan jawaban Anda - internal adalah sedikit kotak hitam, dan Anda telah membantu menjelaskan apa yang tampak seperti skenario yang sangat buruk untuk kinerja (bahkan jika Anda adalah kasus tepi).
Max Vernon