Можно ли дефрагментировать системные таблицы 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);


Дополнительная запрашиваемая информация

Я использовал адаптацию запроса Aaron ниже использования пула буферов для проверки системных таблиц, и это показало, что в пуле буферов есть десятки ГБ системных таблиц только для одной базы данных, причем в некоторых случаях ~ 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

Вы уверены, что положительно и точно определили эту системную таблицу как единственный источник «ненужного давления на буферный пул, а также отрицательно влияет на производительность операций, таких как вычисление размера всех таблиц в базе данных»? Вы уверены, что эта системная таблица не управляется самостоятельно таким образом, что (а) фрагментация сводится к минимуму или контролируется тайно или просто (б) эффективно управляется в памяти, так что уровни дефрагментации действительно ничего не влияют?

Вы можете увидеть , сколько страниц в использовании, и вы можете видеть , сколько свободного места на страницах , которые находятся в памяти ( 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 ... REORGANIZE для всех системных базовых таблиц . Выполнение этой процедуры на некоторых из наших наиболее (ab) используемых серверов разработки показало, что совокупный размер системных базовых таблиц был урезан до 50 ГБ (с ~ 5 ММ ​​пользовательскими таблицами в системе, что явно является крайним случаем).

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

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

Поэтому я пришел к выводу, что добавление ALTER INDEX...REORGANIZEсистемных базовых таблиц в план обслуживания может оказаться полезным для рассмотрения, но, вероятно, только в том случае, если у вас есть сценарий, когда в базе данных создается необычное количество объектов.

Джефф Паттерсон
источник
+1 и за ваш вопрос, и за ответ - внутренняя часть - это что-то вроде черного ящика, и вы помогли пролить некоторый свет на то, что выглядит как действительно неприятный сценарий для производительности (даже если ваш - крайний случай).
Макс Вернон