Адаптивное обновление индексов 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

См. также

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

Практическое пошаговое руководство по развертыванию и настройке связки «1С:Предприятие 8.3 (x64)» и MS SQL Server 2019 на подготовленном сервере Windows Server 2019. Статья охватывает весь процесс «с нуля»: от установки системных зависимостей и тонкой оптимизации СУБД под специфику 1С (Collation, мгновенная инициализация файлов, лимиты памяти и сетевые протоколы) до создания клиент-серверной базы данных через штатное окно запуска. Материал ориентирован на системных администраторов и специалистов по внедрению, содержит наглядные скриншоты реальной установки, T-SQL скрипт для подготовки учетных записей и итоговый чек-лист работоспособности системы.

17.07.2026    601    user2209040    1    

5

HighLoad оптимизация Администрирование СУБД Программист Россия Бесплатно (free)

Если вы работаете с 1С на PostgreSQL и жалуетесь на тормоза — скорее всего, дело в join predicate pushdown, которого в стандартном PostgreSQL нет. В MS SQL Server этот механизм работает «из коробки», и при миграции именно запросы к виртуальным таблицам 1С бьют по производительности сильнее всего. В этой статье — реальный кейс от Postgres Professional с разбором плана выполнения, ручным экспериментом и доработкой планировщика СУБД, которая ускорила запросы от 22 до 54 000 раз.

16.06.2026    6907    postgres_professional    13    

11

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

Вышел релиз СУБД Tantor Postgres 18, и мы хотим рассказать о его новых возможностях для работы с приложениями на платформе "1С:Предприятие". В обзоре разберем улучшения планировщика, по традиции коснемся работы временных таблиц и не обойдем вниманием вспомогательные утилиты, которые упрощают поиск и диагностику проблем в высоконагруженных системах. За каждым пунктом - реальные запросы 1С, реальные рабочие базы и сотни часов тестирования!

16.06.2026    1829    Tantor    7    

10

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

База 1С за несколько лет эксплуатации разрослась, - стала большой, медленно работает, требует много места и времени для копирования и прочего обслуживания. Нужна ли обязательно свертка или можно обойтись более «мягкими» средствами. Делюсь своим опытном как для новых конфигураций, так и для старых УПП, УТ 10…

01.06.2026    6827    2ncom    30    

11

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

Статья рассказывает об опыте перевода больших баз с MSSQL на Postgres и годовой эксплуатации после перехода. Показано, с какими ограничениями утилиты ibcmd можно столкнуться при миграции больших баз и какие подходы помогают безопасно обходить эти проблемы. Приведены наиболее интересные кейсы, выявленные в эксплуатации: особенности настроек Postgres, поведение оптимизатора, тонкости работы логики и статистики, а также редкие, но критичные ситуации с производительностью. Материал будет полезен тем, кто планирует переход на Postgres и хочет заранее понимать реальные риски, подводные камни и проверенные практики их преодоления.

20.04.2026    7790    berserg    12    

26

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

Прокачиваем Постгрес с помощью пользовательских функций и процедур.

02.03.2026    3173    SerVer1C    3    

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