Адаптивное обновление индексов MS SQL

10.04.25

База данных - Администрирование СУБД

Публикация размещена исключительно в образовательных целях и подходит только для платформы версии 8.3.25.1501.
Использует недокументированные средства доступа к базе данных 1С. Прямое обращение к СУБД нарушает лицензионное соглашение,
может изменить поведение платформы, привести к разрушению базы данных, скомпрометировать данные,
а также привести к отказу в официальной поддержке Фирмы 1С.
Всегда надо обслуживать индексы SQL. В том числе по рекомендации самой 1С. Но обслуживать все и сразу - долго, тяжело серверу и, главное, бессмысленно. Особенно для больших баз. Данный скрипт выбирает, что надо делать, и делает это автоматически. Готового полного аналога не нашел, поэтому сделал этот. Можно примерять для любых конфигураций и платформ 1С. Проверено на 8.3.25.1501.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Адаптивное обновление индексов MS SQL:
.sql 7,49Kb
4
4 Скачать (1 SM) Купить за 1 850 руб.
Адаптивное обновление индексов MS SQL: 25
.sql 7,49Kb
1
1 Скачать (1 SM) Купить за 1 850 руб.

Параметрический  -каждый параметр можно подстроить под себя

Успешно работает на нескольких серверах

Протестирован на 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;
 

 

Обслуживание индексов MS SQL

См. также

Администрирование СУБД Системный администратор Платформа 1С v8.3 Россия Бесплатно (free)

В очередной раз столкнулся с тем, что очередные обновления тонкого клиента 1С для Mac OS, загруженные с сайта обновления ПО 1С, не устанавливаются через стандартный инсталлятор и дают ошибку. Но можно все установить вручную без сторонних приложений. Описываю процесс ручной установки тонкого клиента для платформы 8.3.27.1559 на Маке с OS Sequoia 15.5.

02.06.2025    807    user1914479    11    

3

HighLoad оптимизация Администрирование СУБД Системный администратор Программист Платформа 1С v8.3 Бесплатно (free)

В финальной статье по докладу «Дамп – не приговор, а повод задуматься», с которым выступили на осенней конференции INFOSTART TECH EVENT 2024, рассказываем, чем может быть полезна информация, полученная из дампа.

27.05.2025    1411    it-expertise    0    

12

Администрирование СУБД Системный администратор Платформа 1С v8.3 Бесплатно (free)

Клиент-серверная архитектура 1С Предприятия 8.3 подразумевает работу в связке с так называемой системой управления базами данных (СУБД). Одной из самых распространённых и популярных до сих пор остается MS SQL Server.

19.05.2025    1289    Kostin1978    4    

4

HighLoad оптимизация Администрирование СУБД Системный администратор Программист Платформа 1С v8.3 Бесплатно (free)

Во второй статье по докладу «Дамп – не приговор, а повод задуматься», с которым выступили на конференции INFOSTART TECH EVENT 2024, рассмотрим, какую информацию содержат файлы дампа, чем она полезна и как ее анализировать.

14.04.2025    1354    it-expertise    7    

16

Администрирование СУБД Программист Платформа 1С v8.3 Бесплатно (free)

Где лежат данные идентификаторов, как прочитать, как поменять...

10.04.2025    1180    atdonya    0    

6

HighLoad оптимизация Администрирование СУБД Системный администратор Программист Платформа 1С v8.3 Бесплатно (free)

Опубликовали первую статью по итогам доклада «Дамп – не приговор, а повод задуматься», с которым выступали на конференции INFOSTART TECH EVENT 2024.

25.03.2025    969    it-expertise    7    

10
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. paulwist 12.02.25 10:50 Сейчас в теме
DECLARE @threshold_modification_pct INT = 1; -- Сколько процентов считать важными изменениями. Таблицы большие и 1% на миллионах –уже 10 000…


Если уж речь про большие таблицы, то тип INT явно не подходит для дробных процентов :)
5. GreyCardinal 4 13.02.25 10:34 Сейчас в теме
(1Согласен но в реальности на нашей базе (есть и по 200кк строк) оптимально что инт
не будет колебаний расчитывать до долей процентов параметр )
2. PerlAmutor 159 13.02.25 06:31 Сейчас в теме
Есть такой живой проект от Ola Hallengren с 2008 года. Умеет многое. Виктор Богачев упоминал, что он не панацея т.к. для достаточно больших баз требуются определенные исключения некоторых таблиц из обработки, плюс там вроде как нет реальной параллельности обслуживания индексов.

https://github.com/olahallengren/sql-server-maintenance-solution
3. paulwist 13.02.25 09:58 Сейчас в теме
(2)
плюс там вроде как нет реальной параллельности обслуживания индексов.


Это невозможно by design для одной таблицы, поскольку при параллельном процессе двух разных сессий на табличку накладываются несовместимые блокировки.
8. PerlAmutor 159 13.02.25 19:05 Сейчас в теме
(3) Да хотя бы для разных - тоже нету.
4. GreyCardinal 4 13.02.25 10:33 Сейчас в теме
(2)Смотрел
почему сделал свой
1-понятнее что делает - без излишков
2 не нужны доп функции на сервере создавать
3-сам смотрит какие обрабатывать - минимум настроек

у нас работает на ДО и ЗУП
разные базы - для админов настройка одна
6. redfred 13.02.25 15:12 Сейчас в теме
Автоматически создаваемая статистика ( '_WA%' ) тут не обновляется, получается?
7. GreyCardinal 4 13.02.25 17:10 Сейчас в теме
(6) Никто не мешает закомментить
AND stat.NAME NOT LIKE ( '_WA%' )
но как правило раз стоит автосоздание - наверняка и автообновление
но на автообновление уже нарвались - сносит что было и обновляет по части
поэтому выбрали управляемое действо
9. redfred 14.02.25 07:00 Сейчас в теме
(7)
Никто не мешает закомментить
AND stat.NAME NOT LIKE ( '_WA%' )


Боюсь, что не поможет. У вас список на основе sys.objects строится, там в принципе статистик нет.

(7)
но как правило раз стоит автосоздание - наверняка и автообновление


Наверняка. Но ведь и для остальных, не автосоздаваемых, оно стоит, но ведь их скриптом-то обновляете.

Ну ладно, бог с ним. Скажите, из каких соображений обрабатываются только топ 10 индексов? При том, что сортировка закомментирована.
10. GreyCardinal 4 14.02.25 10:12 Сейчас в теме
(9) Очепятка от теста- убрал

автообновление убрали у всех

так как данные меняются - автообновление берет часть для статистики - в итоге ломается
11. redfred 14.02.25 10:58 Сейчас в теме
(10) Понятно. Т.е автообновление отключено, но, при этом, часть статистик выпадает из обработки (не из-за sys.objects, как мне сперва показалось, на джойне с dm_db_index_usage_stats). Ну, ок, тут не берусь судить насколько это принципиально именно для 1С
12. GreyCardinal 4 14.02.25 11:30 Сейчас в теме
(11) Скажем так - анализ текущих запросов не выявил других проблем
Если найдутся - будем решать
13. GreyCardinal 4 14.02.25 12:07 Сейчас в теме
(11)
берутся как раз не все - а которые часто используются-минимум кастомизации
в 1с запрещено лицензией создавать свои
- поэтому для 1с этот скрип "кошерный"
14. redfred 14.02.25 12:34 Сейчас в теме
По текущей логике скрипта автосоздаваемые статистики не берутся ни при каком условии. Они у вас безальтернативно отфильтровываются, т.к. они "безиндексные" и про них нет записей в соотв. dmv.
Но если проблем нет - то проблем нет
Оставьте свое сообщение