Чи можна системні таблиці SQL Server дефрагментувати?


15

У нас є кілька баз даних, в яких створюється і випадає велика кількість таблиць. З того, що ми можемо сказати, SQL Server не проводить жодного внутрішнього обслуговування системних базових таблиць , це означає, що вони можуть з часом сильно роздроблені та роздуватися. Це надає зайвий тиск на буферний пул, а також негативно впливає на виконання операцій, таких як обчислення розміру всіх таблиць у базі даних.

Хтось має пропозиції щодо мінімізації фрагментації цих основних внутрішніх таблиць? Одне очевидне рішення могло б уникнути створення такої кількості таблиць (або створити всі перехідні таблиці в tempdb), але для цього питання скажімо, що програма не має такої гнучкості.

Редагувати: Подальші дослідження показують це невідповідальне запитання , яке виглядає тісно пов’язаним і вказує на те, що певна форма технічного обслуговування вручну ALTER INDEX...REORGANIZEможе бути можливою.


Початкові дослідження

Метадані про ці таблиці можна переглянути в 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

Однак, sys.dm_db_index_physical_statsсхоже, не підтримується перегляд фрагментації цих таблиць:

-- 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'
)

Сценарії Ола Галленгрена також містять параметр, який враховує дефрагментацію is_ms_shipped = 1об'єктів, але процедура мовчки ігнорує базові таблиці системи, навіть якщо цей параметр включений. Ола уточнив, що це очікувана поведінка; msdb.dbo.backupsetрозглядаються лише таблиці користувачів (не системні таблиці), які є ms_shipped (наприклад ).

-- 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);


Додаткова запитувана інформація

Я використав адаптацію запиту Аарона під використанням буфера пулів системної таблиці перевірити, і це виявило, що в буферному пулі є десятки ГБ системних таблиць лише для однієї бази даних, причому ~ 80% цього простору в деяких випадках є вільним місцем .

-- 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

введіть тут опис зображення

Відповіді:


11

Ви впевнені, що позитивно та точно визначили цю системну таблицю як єдине джерело "зайвого тиску на буферний пул, а також негативно впливає на виконання операцій, таких як обчислення розміру всіх таблиць у базі даних"? Ви впевнені, що дана системна таблиця не керується таким чином, що (a) фрагментація мінімізована або таємно перевіряється, або просто (b) керується ефективно в пам’яті, щоб рівні дефрагментації насправді нічого не впливали?

Ви можете побачити , скільки сторінок в використанні, і ви можете бачити , скільки вільного місця на сторінках , які знаходяться в пам'яті ( page_free_space_percentзавжди NULLв розподілах DMF, але це доступно з буфера DMV) - це повинно дати вам деяке уявлення якщо те, про що ти турбуєшся, насправді те, про що ти повинен турбуватися:

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;

Якщо ваша кількість сторінок невелика (як, мабуть, <10000 для системних таблиць) або якщо вільний простір "низький" (не впевнений, які ваші типові пороги для reorg / rebuild), зосередьтеся на інших, більш цікавих, низько висячих фруктах .

Якщо ваша кількість сторінок велика, а вільний простір "високий", добре, то, можливо, я даю SQL Server занадто багато кредитів для власного самообслуговування. Як ви показали з іншого питання , це працює ...

ALTER INDEX ALL ON sys.syscolpars REORGANIZE;

... і робить зменшення фрагментації. Хоча це може вимагати підвищених дозволів (я не намагався як піон).

Можливо, ви можете просто робити це періодично, як частину власного обслуговування, якщо це відчуває вас добре та / або маєте будь-які докази того, що це взагалі має позитивний вплив на вашу систему.


Я додав ще одну відповідь, узагальнюючи те, що ми закінчили, і потім очистив попередні коментарі. Ще раз дякую за вашу допомогу!
Джефф Паттерсон

7

На основі рекомендацій з відповіді Аарона, а також додаткових досліджень, ось короткий опис підходу, який я застосував.

З того, що я можу сказати, варіанти перевірки фрагментації базових таблиць системи обмежені. Я пішов вперед і подав проблему Connect, щоб забезпечити кращу видимість, але тим часом, здається, що такі варіанти включають вивчення буферного пулу або перевірка середнього числа # байтів у рядку.

Потім я створив процедуру для виконання ALTER INDEX ... РЕОРГАНІЗАЦІЇ на всіх базових таблицях системи . Виконання цієї процедури на декількох найбільш використовуваних (ab) серверах розробників показало, що сукупний розмір базових таблиць системи був оброблений до 50 Гб (з ~ 5 ММ ​​таблиць користувачів у системі, настільки очевидно, крайній випадок).

Одне з наших нічних завдань з обслуговування, яке допомагає очистити багато таблиць користувачів, створених за допомогою різних тестів та розробок, раніше займало близько 50 хвилин. Поєднання sp_whoisactive, sys.dm_os_waiting_tasksі DBCC PAGEпоказало , що чекає переважав введення / виведення на системній базові таблицях.

Після реорганізації всіх базових таблиць системи завдання технічного обслуговування знизилося до ~ 15 хвилин. Були ще деякі очікування вводу-виводу, але вони були значно зменшені, можливо, через більшу кількість даних, що залишаються в кеші та / або більше читальних головах через меншу фрагментацію.

Отже, мій висновок полягає в тому, що додавання ALTER INDEX...REORGANIZEдо базових таблиць системи в план обслуговування може бути корисною для розгляду, але, ймовірно, лише за наявності сценарію, коли в базі даних створюється незвична кількість об'єктів.


+1 для обох вашого питання і відповіді - Нутрощі трохи чорного ящика, і ви допомогли пролити світло на те , що виглядає як дуже неприємний сценарій для виконання (навіть якщо у вас є ребро випадок).
Макс Вернон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.