Дефрагментация индексов MS SQL для платформы 8.3.22

15.11.23

База данных - Инструменты администратора БД

Начиная с 8.3.22 фирма "1С" убрала блокировки БД на уровне страниц; если БД расположена в MS SQL, то стала возникать проблема при дефрагментации индексов с использованием команды ALTER INDEX REORGANIZE. Предлагаю модификацию известного скрипта, который позволяет обойти эту проблему.

Файлы

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

Наименование Скачано Купить файл
(только для физ. лиц)
Скрипт для дефрагментация индексов для нескольких баз MS SQL
.sql 3,24Kb
33 1 850 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

Начиная с 8.3.22 фирма "1С" убрала блокировки БД на уровне страниц, если БД расположена в MS SQL, то в индексах параметр Allow page locks стал равен False.

Проблема в том, что при дефрагментации индексов с использованием команды ALTER INDEX REORGANIZE возникает ошибка "The index ... on table ....... cannot be reorganized because page level locking is disabled.".

Предлагаю модификацию скрипта с сайта Microsoft, который позволяет обойти эту проблему.

-- Ensure a USE <databasename> statement has been executed first.
SET NOCOUNT ON;

DECLARE @objectid INT;
DECLARE @indexid INT;
DECLARE @partitioncount BIGINT;
DECLARE @schemaname NVARCHAR(130);
DECLARE @objectname NVARCHAR(130);
DECLARE @indexname NVARCHAR(130);
DECLARE @allowpagelocks INT;
DECLARE @partitionnum BIGINT;
DECLARE @partitions BIGINT;
DECLARE @frag FLOAT;
DECLARE @command NVARCHAR(4000);

-- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function
-- and convert object and index IDs to names.
SELECT object_id AS objectid,
    index_id AS indexid,
    partition_number AS partitionnum,
    avg_fragmentation_in_percent AS frag
INTO #work_to_do
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED')
WHERE avg_fragmentation_in_percent > 10.0
    AND index_id > 0;

-- Declare the cursor for the list of partitions to be processed.
DECLARE partitions CURSOR
FOR
SELECT *
FROM #work_to_do;

-- Open the cursor.
OPEN partitions;

-- Loop through the partitions.
WHILE (1 = 1)
BEGIN;

    FETCH NEXT
    FROM partitions
    INTO @objectid,
        @indexid,
        @partitionnum,
        @frag;

    IF @@FETCH_STATUS < 0
        BREAK;

    SELECT @objectname = QUOTENAME(o.name),
        @schemaname = QUOTENAME(s.name)
    FROM sys.objects AS o
    INNER JOIN sys.schemas AS s
        ON s.schema_id = o.schema_id
    WHERE o.object_id = @objectid;

    SELECT @indexname = QUOTENAME(name), @allowpagelocks = allow_page_locks
    FROM sys.indexes
    WHERE object_id = @objectid
        AND index_id = @indexid;

    SELECT @partitioncount = count(*)
    FROM sys.partitions
    WHERE object_id = @objectid
        AND index_id = @indexid;

    -- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding.
    IF @frag < 30.0
		SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE';

    IF @frag >= 30.0
        SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD';

    IF @partitioncount > 1
        SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS NVARCHAR(10));

	IF @frag < 30.0 AND @allowpagelocks = 0
		SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' SET (ALLOW_PAGE_LOCKS = ON);' 
		    + @command + N'; ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' SET (ALLOW_PAGE_LOCKS = OFF)';

    EXEC (@command);

    PRINT N'Executed: ' + @command;
END;

-- Close and deallocate the cursor.
CLOSE partitions;

DEALLOCATE partitions;

-- Drop the temporary table.
DROP TABLE #work_to_do;
GO

К публикации приложен скрипт для дефрагментации индексов для нескольких баз.

дефрагментация 8.3.22

См. также

SALE! 15%

Инструментарий разработчика Чистка данных Свертка базы Инструменты администратора БД Системный администратор Программист Руководитель проекта 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Россия Платные (руб)

Инструмент представляет собой обработку для проведения свёртки или обрезки баз данных. Работает на ЛЮБЫХ конфигурациях (УТ, БП, ERP, УНФ, КА и т.д.). Поддерживаются серверные и файловые базы, управляемые и обычные формы. Может выполнять свертку одновременно в несколько потоков. А так же автоматически, без непосредственного участия пользователя. Решение в Реестре отечественного ПО

8400 7140 руб.

20.08.2024    32735    201    104    

188

Инструменты администратора БД Инструментарий разработчика Роли и права Программист 1С v8.3 1C:Бухгалтерия Россия Платные (руб)

Расширение позволяет без изменения кода конфигурации выполнять проверки при вводе данных, скрывать от пользователя недоступные ему данные, выполнять код в обработчиках. Не изменяет данные конфигурации, легко устанавливается практически на любую конфигурацию на управляемых формах.

15000 руб.

10.11.2023    15572    66    33    

84

Инструменты администратора БД Роли и права Системный администратор Программист Пользователь 8.3.14 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Документооборот 1С:Зарплата и кадры государственного учреждения 3 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Платные (руб)

Роли… Вы тратите много времени и сил на подбор ролей среди около 2400 в ERP или 1500 в Рознице 2, пытаясь понять какими правами они обладают? Вы все время смотрите права в конфигураторе или отчетах чтоб создать нормальные профили доступа? Вы хотите наглядно видеть какие права дает профиль и редактировать все в простом виде? А может хотите просто указать подсистему и дать права на просмотр и добавление на объекты и не лезть в дебри прав и чтоб обработка сама подобрала нужные роли? Все это теперь стало возможно! Обновление от 17.06.2025, версия 1.3

19200 руб.

06.12.2023    14283    61    8    

90

Закрытие периода Инструменты администратора БД Корректировка данных Бухгалтер Пользователь Бухгалтерский учет 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Платные (руб)

Расширение «Оперативное проведение» в 4 раза уменьшает время проведения документов и закрытия месяца. Является комплексным решением проблем 62 и 60 счетов. Оптимизирует проведение при включенной функциональной опции «Раздельный учет НДС». Используется в более 10 организациях уже 2 года. Совместимо с конфигурацией Бухгалтерия 3.0 (+КОРП).

14400 руб.

29.04.2020    37407    115    152    

82

Инструменты администратора БД Системный администратор 1С v8.3 1С:Комплексная автоматизация 1.х 1С:Управление производственным предприятием Платные (руб)

Конфигурация Комплексная автоматизация 1.1 (и УПП 1.3 тоже) хранит файлы и изображения в справочнике Хранилище дополнительной информации в реквизите Хранилище типа ХранилищеЗначений. Та же история с ВложениямиЭлектроннойПочты. Но при этом присоединенные файлы в Электронном документообороте хранит в томах на диске. Эта доработка позволяет использовать стандартный механизм хранения файлов, изображений и вложений электронных писем в томах на диске. При этом можно разделить тома хранения по объектам конфигурации.

4200 руб.

10.11.2015    63968    99    59    

82

Инструменты администратора БД Пользователь 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Платные (руб)

Многие сталкиваются с проблемой когда изображения, находящиеся в базе разные по объему и размерам. Менеджеры могут добавить файлы в очень высоком разрешении, объемом свыше 20 Мегабайт. База данных становится слишком большой, выгрузка на сайт идёт медленно и требуется много место на хостинге. Как сжать картинки и уменьшить размер базы 1С? Это можно сделать с помощью данной обработки. Существует возможность выбрать различные варианты для того чтобы уменьшить картинки: в разы, в процентах от первоначального объема, а также сделать картинки одинаковой ширины. В результате размер базы 1С значительно сократится (в зависимости от количества и размера картинок), а изображения станут небольшого объема, равными по ширине, почти без потери качества. Работает на управляемых формах для УТ 11, КА, ERP.

3000 руб.

21.07.2022    11154    14    4    

22

Администрирование Инструменты администратора БД Удаленное управление Системный администратор 1С v8.3 1С:Зарплата и Управление Персоналом 3.x Платные (руб)

Расширение разработано для автоматизации интеграции «1С:Зарплата и управление персоналом (редакция 3.1)» с сервисом Яндекс 360 через платформу «n8n». Расширение позволяет автоматически создавать учетные записи Яндекс для новых сотрудников, обновлять данные существующих сотрудников и блокировать учетные записи уволенных сотрудников. Обмен данными осуществляется через API Яндекс 360 с использованием промежуточного сервера платформы n8n, что обеспечивает гибкость, масштабируемость и упрощение интеграционных процессов.

3600 руб.

03.04.2025    860    2    0    

2
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
3. baturo 38 15.11.23 12:48 Сейчас в теме
(1) Так и делается, но не для всех индексов, а только для тех, где снять флаг Allow page lock:

IF @frag < 30.0 AND @allowpagelocks = 0
		SET @command = N'ALT ER   INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' SET (ALLOW_PAGE_LOCKS = ON);' 
		    + @command + N'; ALT ER   INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' SET (ALLOW_PAGE_LOCKS = OFF)';
2. SerVer1C 925 15.11.23 11:14 Сейчас в теме
EXEC sp_msforeachtable 'ALT ER INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON)'
EXEC sp_msforeachtable 'ALT ER INDEX ALL ON ? REORGANIZE WITH (LOB_COMPACTION = ON)'
EXEC sp_msforeachtable 'ALT ER INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = OFF, ALLOW_ROW_LOCKS = ON)'
GO

* <ALTER> пишется слитно

3 строчки вместо портянки
(не благодарите)
user926893; rrustam11983; medexe; +3 Ответить
4. paulwist 20.11.23 14:59 Сейчас в теме
(2)
3 строчки вместо портянки


Ммм, как минимум 4-е строчки :)

USE MyDB
5. Alias 176 24.11.23 12:05 Сейчас в теме
разбирали ещё полтора месяца назад:
https://partners.v8.1c.ru/forum/topic/2152862

Там же привели все варианты, которые тут описывают, и ещё вот такой:

sp_msforeachtable N'
ALT ER   INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = ON)
DBCC INDEXDEFRAG (<имя базы данных>, ''?'')
ALT ER   INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = OFF)
'


P.S. Почему на Инфостарте слово ALTER вставляется в сообщение с пробелом? Я так не писал. И не исправляется, зараза. Конечно, там просто ALT ER INDEX ALL ....
6. baturo 38 27.11.23 05:57 Сейчас в теме
(5)
ели все вар

(5)


P.S. Почему на Инфостарте слово ALTER вставляется в сообщение с пробелом? Я так не писал. И не исправляется, зараза. Конечно, там просто ALT ER INDEX ALL ...


Не все индексы требуют реорганизации, зачем тратить ресурс сервера - сначала установить флаг ALLOW_PAGE_LOCKS для всех индексов, а затем его сбрасывать.

В данной версии скрипта флаг устанавливается и сбрасывается только тогда, когда требуется реорганизация индекса;
это более оптимально.
7. user866660 22.07.24 14:46 Сейчас в теме
(5)
Почему на Инфостарте слово ALTER вставляется в сообщение с пробелом?


От SQL Injection защищаются, наверное :)
8. Xershi 1535 02.12.24 19:23 Сейчас в теме
Адаптировал данный скрипт под версию из публикации Регламентные операции с индексами
-------------------------------------------
-- НАСТРАИВАЕМЫЕ ПАРАМЕТРЫ
-- База данных для анализа
--USE WorkBase
-- Убедитесь, что сначала был выполнен оператор USE <имя_базы_данных>.

-------------------------------------------
-- СЛУЖЕБНЫЕ ПЕРЕМЕННЫЕ 
DECLARE @object_id INT; -- ID объекта
DECLARE @index_id INT; -- ID индекса
DECLARE @partition_count BIGINT; -- количество секций, если индекс секционирован
DECLARE @schemaname NVARCHAR(130); -- имя схемы, в которой находится таблица
DECLARE @objectname NVARCHAR(130); -- имя таблицы
DECLARE @indexname NVARCHAR(130); -- имя индекса
DECLARE @allowpagelocks INT; -- разрешить блокировку страницы
DECLARE @partitionnum BIGINT; -- номер секции
--DECLARE @partitions BIGINT; -- не используется
DECLARE @fragmentation_in_percent FLOAT; -- процент фрагментации индекса
DECLARE @command NVARCHAR(4000); -- инструкция T-SQL для дефрагментации либо реиндексации

-------------------------------------------
-- ТЕЛО СКРИПТА

-- Отключаем вывод количества возвращаемых строк, это несколько ускорит обработку
SET NOCOUNT ON;

-- Удалим временные таблицы, если вдруг они есть.
IF OBJECT_ID('tempdb.dbo.#work_to_do') IS NOT NULL DR OP   TABLE #work_to_do

-- Отбор таблиц и индексов с помощью системного представления sys.dm_db_index_physical_stats
-- и конвертируем идентификаторы объектов и индексов в имена.
-- Отбор только тех объектов которые:
--  являются индексами (index_id > 0)
--  фрагментация которых более 5%
--  количество страниц в индексе более 128
SEL ECT
    object_id AS object_id,
    index_id AS index_id,
    partition_number AS partitionnum,
    avg_fragmentation_in_percent AS fragmentation_in_percent
INTO #work_to_do
FR OM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED')
WHERE index_id > 0 
    AND avg_fragmentation_in_percent > 5.0
    AND page_count > 128;

-- Объявляем курсор для списка секций, которые необходимо обработать.
DECLARE partitions CURSOR
FOR
SEL ECT *
FR OM #work_to_do;

-- Открываем курсор.
OPEN partitions;

-- Цикл по секциям.
WHILE (1 = 1)
BEGIN;

    FETCH NEXT
    FR OM partitions
    INTO @object_id,
        @index_id,
        @partitionnum,
        @fragmentation_in_percent;

    IF @@FETCH_STATUS < 0
        BREAK;

    -- Собираем имена объектов по ID
    SEL ECT @objectname = QUOTENAME(o.name),
        @schemaname = QUOTENAME(s.name)
    FR OM sys.objects AS o
    INNER JOIN sys.schemas AS s
        ON s.schema_id = o.schema_id
    WH ERE o.object_id = @object_id;

    SELECT @indexname = QUOTENAME(name),
        @allowpagelocks = allow_page_locks
    FR OM sys.indexes
    WH ERE object_id = @object_id
        AND index_id = @index_id;

    SELECT @partition_count = count(*)
    FR OM sys.partitions
    WH ERE object_id = @object_id
        AND index_id = @index_id;

    -- Если фрагментация менее или равна 30%, тогда дефрагментация, иначе реиндексация.
    IF @fragmentation_in_percent < 30.0
        SET @command = N'ALT ER   INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE';

    IF @fragmentation_in_percent >= 30.0
        SET @command = N'ALT ER   INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD';

    IF @partition_count > 1
        SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS NVARCHAR(10));

    IF @fragmentation_in_percent < 30.0 AND @allowpagelocks = 0
        SET @command = N'ALT ER   INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' SET (ALLOW_PAGE_LOCKS = ON);'
            + @command + N'; ALT ER   INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' SET (ALLOW_PAGE_LOCKS = OFF)';

    -- Выполняем команду
    EXEC (@command);

    PRINT N'Index: object_id=' + STR(@object_id) + ', index_id=' + STR(@index_id) + ', fragmentation_in_percent=' + STR(@fragmentation_in_percent);
    PRINT N'Executed: ' + @command;
END;

-- Закрытие курсора
CLOSE partitions;

DEALLOCATE partitions;

-- Удаление временной таблицы
DR OP   TABLE #work_to_do;
GO
Показать

Как я понимаю оператор USE нужно выполнить, чтобы гарантировать выполнение на нужной базе. Но если делать через Агент SQL Server - Задания, то это можно не делать, т.к. там явно указывается для какой базы выполняется скрипт. А переменную partitions нигде не используется, поэтому эти операторы закомментировал.
Кстати у кого есть сервер 1С до 8.3.22 данный скрипт будет работать?
9. Xershi 1535 12.12.24 15:49 Сейчас в теме
(8) если будете копировать сприпт, проверьте все конструкции. В текст вставлены лишние пробелы. Наверное защита форума.
В частности синтаксис около:
DR OP 
 TABLE
SEL ECT
FR OM
WHERE
ALT ER 
 INDEX

Дробит слова и вставляет от 1 до 2 лишних пробелов. Поэтому просто скопировать не получится.
10. 1Pawel 2 14.01.25 15:11 Сейчас в теме
Понравился скрипт от Tavalik, доработанный Филипповым Сергеем (здесь).
Есть опция обновления статистики после реорганизации.
Поддержка параллелизма, сортировки в tempdb, реиндексация онлайн некоторых типов индексов.
Процент фрагментации для реорганизации и реиндексации выведен в блок переменных.
Более подробный вывод лога.

Я адаптировал этот скрипт под MSSQL 2012, где не поддерживаются параметры UPDATE STATISTICS до MSSQL 2014. Убрал неподдерживаемые параметры Rebuild online в редакциях Standard. Обновление статистики при реорганизации включено всегда.
Прикрепленные файлы:
ReindexRebuild_1Pawel.sql
ReindexRebuild_Filippov.sql
ReindexRebuild_AnyBases_Filippov.sql
Оставьте свое сообщение