Адаптивное обновление индексов MS SQL
База данных - Администрирование СУБД
Использует недокументированные средства доступа к базе данных 1С. Прямое обращение к СУБД нарушает лицензионное соглашение,
может изменить поведение платформы, привести к разрушению базы данных, скомпрометировать данные,
а также привести к отказу в официальной поддержке Фирмы 1С.
Файлы
ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.
Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний
Оформите подписку на компанию для решения рабочих задач
Оформить подписку и скачать решение со скидкойВы можете заказать платную доработку или адаптацию этой разработки под вашу конфигурацию на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
Параметрический -каждый параметр можно подстроить под себя
Успешно работает на нескольких серверах
Протестирован на MS SQL 2019
Внимание!
Скрипт обрабатывает только часто используемые индексы
чтобы убрать тормоза на других. редко используемых объектах - настройте по ним пртнудительно обновление статистики ( например для отчета по производительности)
Скрипт адаптивной обработки индекса, если индекс используется активно (параметр) и фрагментирован (параметр) или статистика неактуальна (параметр), то выполняет команды по обслуживанию индекса.
Каждая команда выводит в комментарий - почему она выполнилась.
Также можно как показать, что будет делать, так и выполнить сразу
DECLARE @OnlyShow INT = 0; --1 = только показать, 0 = еще и выполнить
DECLARE @threshold_modification_pct INT = 1; -- Сколько процентов считать важными изменениями. Таблицы большие и 1% на миллионах –уже 10 000…
DECLARE @minrows INT = 100; -- брать если строк больше в индексе
DECLARE @minused INT = 1000; -- если использовали больше чем 1000 раз
DECLARE @minSteps INT = 10; -- не берем индкесы если они с точки статистики бестолковые
DECLARE @maxRows INT = 100000; -- Или количество строк меньше чем то игнор предыдущее условие
DECLARE @FragsLevel INT = 5; -- дефраг только если больше
DECLARE @FragsLevelRebuild INT = 30; -- rebuild если фрагментация больше
DECLARE @EnterpriseEdition INT = 0; --case when SERVERPROPERTY ('edition')='Enterprise Edition (64-bit)' then 1 else 0 end
---- служебные переменные
DECLARE @command NVARCHAR(500);
DECLARE @TableName SYSNAME;
DECLARE @IndexName SYSNAME;
DECLARE @modification_counter NVARCHAR(200);
DECLARE @Table_rows NVARCHAR(200);
DECLARE @Table_used NVARCHAR(200);
DECLARE @Steps NVARCHAR(200);
DECLARE @avg_fragmentation_in_percent NUMERIC;
DECLARE @levelForDefrag NUMERIC;
DECLARE @Frag NVARCHAR(200);
DECLARE @Variant NVARCHAR(20);
DECLARE indexes CURSOR FOR
SELECT
obj.NAME [table],
stat.NAME [index],
modification_counter [modification_counter],
sp.rows [Table_rows],
user_seeks + user_scans + user_lookups AS Table_used,
sp.steps Steps,
ips.avg_fragmentation_in_percent AS avg_fragmentation_in_percent ,
ips.avg_fragmentation_in_percent AS Frag,
sp.rows * @threshold_modification_pct / 100 AS levelForDefrag,
CASE
WHEN modification_counter >
sp.rows * @threshold_modification_pct / 100
THEN
N'UPDATE STATISTICS'
WHEN ips.avg_fragmentation_in_percent > @FragsLevelRebuild THEN
'REBUILD'
ELSE 'REORGANIZE'
END AS Variant
FROM sys.objects AS obj
INNER JOIN sys.stats AS stat
ON stat.object_id = obj.object_id
CROSS apply sys.Dm_db_stats_properties(stat.object_id, stat.stats_id)
AS
sp
LEFT JOIN (SELECT *
FROM sys.Dm_db_index_physical_stats(Db_id(), NULL, NULL,
NULL, NULL
)) AS ips
ON stat.object_id = ips.object_id
AND stat.stats_id = ips.index_id
INNER JOIN sys.dm_db_index_usage_stats AS s
ON stat.object_id = s.object_id
AND stat.stats_id = s.index_id
WHERE s.database_id = Db_id()
AND obj.type = 'U'
AND stat.NAME NOT LIKE ( '_WA%' )
AND ips.alloc_unit_type_desc = 'IN_ROW_DATA'
AND @minrows < sp.rows
AND ( user_seeks + user_scans + user_lookups ) >= @minused
AND ( ips.avg_fragmentation_in_percent > @FragsLevel
OR ( modification_counter >
sp.rows * @threshold_modification_pct / 100 )
)
AND ( sp.steps > @minSteps
OR @maxRows > sp.rows )
--ORDER BY stat.NAME
; ---(user_seeks + user_scans + user_lookups) desc;
OPEN indexes;
WHILE ( 1 = 1 )
BEGIN
FETCH next FROM indexes INTO @TableName, @IndexName, @modification_counter ,
@Table_rows, @Table_used, @Steps, @avg_fragmentation_in_percent, @Frag,
@levelForDefrag,@Variant;
IF @@FETCH_STATUS < 0
BREAK;
IF @levelForDefrag < @modification_counter
SET @command = N'UPDATE STATISTICS dbo.' + @TableName + ' '
+ @IndexName
+ N' WITH FULLSCAN, MAXDOP=8; -- Steps '
+ @Steps + ', used ' + @Table_used + ', changed '
+ @modification_counter + ' rows of '
+ @Table_rows;
ELSE
SET @command =
CASE
WHEN @variant='REBUILD'
THEN
''
ELSE
N'ALTER INDEX ' + @IndexName + ' on dbo.' + @TableName+ ' SET (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON);'
END
+ N'ALTER INDEX ' + @IndexName + ' on dbo.' + @TableName
+ CASE
WHEN @variant='REBUILD'
THEN
' REBUILD WITH (SORT_IN_TEMPDB = ON, maxdop=8' + case When @EnterpriseEdition=1 then ', online=on' else '' end +')'
ELSE
' REORGANIZE '
END
+ CASE
WHEN @variant='REBUILD'
THEN
''
ELSE
N'; ALTER INDEX ' + @IndexName + ' on dbo.' + @TableName+ ' SET (ALLOW_PAGE_LOCKS = OFF, ALLOW_ROW_LOCKS = ON)'
END
+ '; --- frag = ' + @Frag + '%' + ', rows = ' + @Table_rows;
PRINT N'Executed: ' + @command;
IF @OnlyShow = 1
CONTINUE;
EXEC (@command);
END;
CLOSE indexes;
DEALLOCATE indexes;
Вступайте в нашу телеграмм-группу Инфостарт