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

10.04.25

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

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

Файлы

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

Наименование Скачано Купить файл
Адаптивное обновление индексов MS SQL:
.sql 7,49Kb
6 2 500 руб. Купить
Адаптивное обновление индексов MS SQL: 25
.sql 7,49Kb
1 2 500 руб. Купить

Подписка 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;
 

 

Вступайте в нашу телеграмм-группу Инфостарт

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

См. также

HighLoad оптимизация Администрирование СУБД Разработчик 1С:Предприятие 8 1С:ERP Управление предприятием 2 Бухгалтерский учет Бесплатно (free)

После миграции с MS SQL на PostgreSQL закрытие месяца в 1С:ERP стало идти 8 часов вместо 12 минут. Рассказываем, как мы нашли причину в оценке Hash Join, которую планировщик завышал в миллионы раз, и как исправили её так, что проблемный запрос теперь выполняется за 18 секунд вместо часа.

19.10.2026    971    Tantor    0    

10

Администрирование СУБД HighLoad оптимизация Разработчик 1С:Предприятие 8 1С:ERP Управление предприятием 2 Россия Бесплатно (free)

Большинство материалов о компрессии в PostgreSQL отвечают на вопрос «во сколько раз удалось уменьшить базу». Мы предлагаем посмотреть на проблему с другой стороны — какой ценой достигается эта экономия? В статье разбираем архитектурные компромиссы различных подходов к компрессии страниц, объясняем, почему при разработке CSM в Tantor Postgres отказались от погони за максимальным коэффициентом сжатия, и показываем результаты нагрузочных испытаний на реальных базах 1С.

01.10.2026    1472    Tantor    6    

17

DevOps и автоматизация разработки Администрирование СУБД Групповая разработка (Git, хранилище) Разработчик 1С 8.3 Абонемент ($m)

В корпоративных инсталляциях «1С:Предприятие 8.3» под управлением PostgreSQL всё чаще проявляются архитектурные пределы масштабирования: рост числа пользователей, обязательная маркировка, плотный поток API-интеграций и высокая стоимость простоя. Вводная часть цикла разбирает ключевые факторы современной эксплуатационной нагрузки и формирует инженерную методологию эволюционной модернизации без остановки продуктивного контура. Материал основан на практическом кейсе «Торговый контур» и показывает, как определить целевые метрики (p95, MTTR, APDEX), выстроить наблюдаемость, стабилизировать работу кластера и подготовить инфраструктуру к дальнейшему масштабированию. Публикация задаёт фундамент для последующих частей, посвящённых телеметрии, оптимизации PostgreSQL, CI/CD и архитектурному росту.

1 стартмани

10.09.2026    1540    Ninel_S    0    

6

HighLoad оптимизация Администрирование СУБД Разработчик 1С:Предприятие 8 1С:ERP Управление предприятием 2 Бесплатно (free)

В рамках 18 релиза СУБД Tantor Postgres мы рассказывали об оптимизациях, которые помогают планировщику сделать более точный выбор между Nested Loop и Hash Join. В следующем релизе у нас планируются оптимизации, которые позволят ускорить выполнение как Nested Loop, так и Hash Join. Сегодня мы расскажем об одном из таких методов - фильтре Блума.

31.08.2026    6138    Tantor    3    

18

Администрирование СУБД Системный администратор Разработчик 1С 8.3 Бесплатно (free)

Мы подготовили для сообщества Infostart.ru практическое занятие, в котором каждый желающий сможет: научиться собирать реальные данные о процессах кластера 1С; выявлять «перестарков» — процессы старше периода и без соединений; выполнять безопасный перезапуск (с dry-run и подтверждением); настраивать автоматическую проверку через systemd на Linux; отправлять уведомления (Telegram, почта) при обнаружении проблем; работать с логами, ротацией, профилями кластеров и конфигурацией; развернуть полноценный учебный проект AdminClusterMonitor у себя в тестовой среде.

30.08.2026    1753    Ninel_S    2    

6

Администрирование СУБД Системный администратор 1С:Предприятие 8 Бесплатно (free)

На infostart.ru вышел разбор Ивана Недомолкова «Сервер 1С падает: настройка сбора дампов (logcfg.xml), лимиты памяти и передача дампа в поддержку» - это хорошая инструкция, как ловить и разбирать падение rphost постфактум: logcfg.xml, procdump, анализ дампа. Но там нет ответа на вопрос «а почему кластер вообще прибил процесс сам, ещё до всякого краша». Мы дополняем разбор тремя сводными таблицами лимитов памяти и автомасштабирования кластера - и заодно фиксируем, чем в этой части лицензия ПРОФ урезана относительно КОРП.

12.08.2026    2417    Ninel_S    5    

6

Администрирование СУБД Системный администратор Разработчик Бесплатно (free)

5,5 тысячи пользователей в единой базе 1С, розница в режиме 24/7 и SLA 99,98% – в таких условиях любая авария быстро превращается в очереди на кассах, потерю денег и давление со стороны бизнеса. Показываем, как выстроить процесс аварийно-восстановительных работ: от первых алертов и базового скрининга системы до подключения команды, проверки гипотез и дебрифа после инцидента. Разбираем, как метрики, дашборды, техжурнал, Zabbix, Prometheus, Grafana, Telegram-боты и скрипты помогают не гадать, а быстро находить причину проблемы. На реальных авариях объясняем, почему «быстро» не должно означать «рискованно», как работа над ошибками снижает панику и почему каждая авария может сделать систему надежнее.

11.08.2026    3425    jul.dolganova    9    

24
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
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 162 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 162 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.
Но если проблем нет - то проблем нет
Для отправки сообщения требуется регистрация/авторизация