Регламентные операции с индексами в MS SQL Server (Скрипты для SQL-Server — Часть 2)

В данном вебинаре я расскажу о том, что такое индексы, зачем они нужны, какие регламентные операции необходимо выполнять с индексами, а также будут приведены соответствующие скрипты (для MS SQL-Server) для обслуживания индексов баз данных.

 

 

 

Видео в формате вебинара с подробным разбором всех скриптов:

 

 

Все переменные в скриптах собраны в соответствующем блоке в начале скриптов. Для отправки электронной почты используется предварительно настроенный профиль электронной почты компоненты DataBase Mail. О настройке компоненты можно прочитать, здесь. Все скрипты много раз опробованы в бою и протестированы на версиях MS SQL 2008, 2012, 2016.

Эти и другие скрипты доступны в репозитории: https://github.com/Tavalik/SQL_TScripts

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

Все вебинары по скриптам для SQL:

  1. Автоматизируем «перезаливку» баз (Скрипты SQL-Server — Часть 1)
  2. Регламентные операции с индексами в MS SQL Server (Скрипты SQL-Server — Часть 2)
  3. Еще немного полезных SQL-скриптов (Скрипты SQL-Server — Часть 3)
Было ли данное видео полезно для вас?
Да, очень полезно.
Немного полезно.
Совсем не полезно.
Не то, что я искал(а).
Смотреть результаты
Запись опубликована в рубрике SQL, Видео с метками . Добавьте в закладки постоянную ссылку.


12 Responses to Регламентные операции с индексами в MS SQL Server (Скрипты для SQL-Server — Часть 2)

  1. Сергей говорит:

    Спасибо за уроки. Времени читать тягомотину на сайте MS нет, а здесь коротко, наглядно. Да еще и с конкретными примерами. Правда в репозитарий не могу попасть — пустой экран по ссылке.

    • Виталий Онянов говорит:

      Спасибо за отзыв.

      По поводу ссылки, очень странно, пробовал с разных устройств, у меня проблем нет. Попробуйте зайти через мой профиль: https://github.com/Tavalik

  2. Жан говорит:

    Здравствуйте. После выполнения вашего скрипта (Обслуживание_индексов_БД.sql) (да и не только вашего скрипта, просто он показал ошибку) на одной из баз получаю сообщение:
    Msg 1943, Level 16, State 1, Line 1
    The index «_SystemSettings_1» on table «_SystemSettings» cannot be reorganized because page level locking is disabled.
    В общем не удалось обслуживание. Что-то с таблицей.
    Сталкивались с таким ? Что посоветуете?

    • Аноним говорит:

      Вот причина: https://its.1c.ru/db/metod8dev#content:5837:hdoc:p3

      Важно! Начиная с версии платформы 8.3.22 необходимо выполнять дефрагментацию индексов по следующему алгоритму:

      До дефрагментации индекса необходимо включить страничные блокировки. Пример команды: ALTER INDEX index_name ON table_name SET (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON);
      Выполнить дефрагментацию.
      Обратно выключить страничные блокировки. Пример команды: ALTER INDEX index_name ON table_name SET (ALLOW_PAGE_LOCKS = OFF, ALLOW_ROW_LOCKS = ON);

      Но как это правильно сделать в скрипте тоже не понимаю.

      • Аноним говорит:

        USE [ИмяБазы]
        EXEC sp_MSforeachtable ‘ALTER INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = ON)’
        EXEC sp_MSforeachtable ‘ALTER INDEX ALL ON ? SET (ALLOW_ROW_LOCKS= ON)’
        GO

        после реорганизации

        USE [ИмяБазы]
        EXEC sp_MSforeachtable ‘ALTER INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = OFF)’
        EXEC sp_MSforeachtable ‘ALTER INDEX ALL ON ? SET (ALLOW_ROW_LOCKS= ON)’
        GO

        • Аноним говорит:

          спс

        • Аноним говорит:

          Можно оптимизировать и не делать 2 цикла!
          Соответствтенно до реорганизации:
          EXEC sp_MSforeachtable ‘ALTER INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS= ON)’

          После:
          EXEC sp_MSforeachtable ‘ALTER INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = OFF, ALLOW_ROW_LOCKS= ON)’

  3. Сергей говорит:

    привет. переделал немного ваш скрипт. включил блокировки страниц(без этого — ошибка на базе 1с). кривовато получилось, но работает. 13сек делает 8.5гб базу. Можете помочь с корректным прописанием условия? чтобы если у индекса отключены блокировки страниц — запускать команды @command1 и @cammand2. Если и без них включены — не запускать. Иначе, мой скрипт будет уродовать базы, отключая блокировки там, где они были изначально включены. Скрипт:
    USE [1]

    ——————————————-
    — СЛУЖЕБНЫЕ ПЕРЕМЕННЫЕ
    DECLARE @object_id int; — ID объекта
    DECLARE @index_id int; — ID индекса
    DECLARE @partition_number bigint; — количество секций если индекс секционирован
    DECLARE @schemaname nvarchar(130); — имя схемы в которой находится таблица
    DECLARE @objectname nvarchar(130); — имя таблицы
    DECLARE @indexname nvarchar(130); — имя индекса
    DECLARE @partitionnum bigint; — номер секции
    DECLARE @fragmentation_in_percent float; — процент фрагментации индекса
    DECLARE @command nvarchar(4000); — инструкция T-SQL для дефрагментации либо ренидексации
    DECLARE @command1 nvarchar(4000); — инструкция T-SQL для дефрагментации либо ренидексации
    DECLARE @command2 nvarchar(4000); — инструкция T-SQL для дефрагментации либо ренидексации

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

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

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

    — Отбор таблиц и индексов с помощью системного представления sys.dm_db_index_physical_stats
    — Отбор только тех объектов которые:
    — являются индексами (index_id > 0)
    — фрагментация которых более 5%
    — количество страниц в индексе более 128
    SELECT
    object_id,
    index_id,
    partition_number,
    avg_fragmentation_in_percent AS fragmentation_in_percent
    INTO #work_to_do
    FROM 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 SELECT * FROM #work_to_do;
    OPEN partitions;

    — Цикл по секциям
    FETCH NEXT FROM partitions INTO @object_id, @index_id, @partition_number, @fragmentation_in_percent;
    WHILE @@FETCH_STATUS = 0
    BEGIN

    — Собираем имена объектов по ID
    SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name)
    FROM sys.objects AS o
    JOIN sys.schemas as s ON s.schema_id = o.schema_id
    WHERE o.object_id = @object_id;

    SELECT @indexname = QUOTENAME(name)
    FROM sys.indexes
    WHERE object_id = @object_id AND index_id = @index_id;

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

    — Если фрагментация менее или равна 30% тогда дефрагментация, иначе реиндексация
    IF @fragmentation_in_percent = 30.0

    —перестроение индекса
    SET @command = N’ALTER INDEX ‘ + @indexname + N’ ON ‘ + @schemaname + N’.’ + @objectname + N’ REBUILD WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, SORT_IN_TEMPDB = ON, ONLINE = ON, maxdop = 8 )’;

    IF @partition_number > 1
    SET @command = @command + N’ PARTITION=’ + CAST(@partition_number AS nvarchar(10));

    — Выполняем команду
    EXEC (@command1);
    EXEC (@command);
    EXEC (@command2);
    PRINT N’Index: object_id=’ + STR(@object_id) + ‘, index_id=’ + STR(@index_id) + ‘, fragmentation_in_percent=’ + STR(@fragmentation_in_percent);
    PRINT N’Executed: ‘ + @command;

    — Следующий элемент цикла
    FETCH NEXT FROM partitions INTO @object_id, @index_id, @partition_number, @fragmentation_in_percent;

    END;

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

    — Удаление временной таблицы
    DROP TABLE #work_to_do;

    GO

  4. Сергей говорит:

    —В первом сообщении не полностью вставился скрипт((

    Привет. переделал немного ваш скрипт. включил блокировки страниц(без этого — ошибка на базе 1с). кривовато получилось, но работает. 13сек делает 8.5гб базу. Можете помочь с корректным прописанием условия? чтобы если у индекса отключены блокировки страниц — запускать команды @command1 и @cammand2. Если и без них включены — не запускать. Иначе, мой скрипт будет уродовать базы, отключая блокировки там, где они были изначально включены. Скрипт:
    USE [1]

    ——————————————-
    — СЛУЖЕБНЫЕ ПЕРЕМЕННЫЕ
    DECLARE @object_id int; — ID объекта
    DECLARE @index_id int; — ID индекса
    DECLARE @partition_number bigint; — количество секций если индекс секционирован
    DECLARE @schemaname nvarchar(130); — имя схемы в которой находится таблица
    DECLARE @objectname nvarchar(130); — имя таблицы
    DECLARE @indexname nvarchar(130); — имя индекса
    DECLARE @partitionnum bigint; — номер секции
    DECLARE @fragmentation_in_percent float; — процент фрагментации индекса
    DECLARE @command nvarchar(4000); — инструкция T-SQL для дефрагментации либо ренидексации
    DECLARE @command1 nvarchar(4000); — инструкция T-SQL для дефрагментации либо ренидексации
    DECLARE @command2 nvarchar(4000); — инструкция T-SQL для дефрагментации либо ренидексации

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

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

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

    — Отбор таблиц и индексов с помощью системного представления sys.dm_db_index_physical_stats
    — Отбор только тех объектов которые:
    — являются индексами (index_id > 0)
    — фрагментация которых более 5%
    — количество страниц в индексе более 128
    SELECT
    object_id,
    index_id,
    partition_number,
    avg_fragmentation_in_percent AS fragmentation_in_percent
    INTO #work_to_do
    FROM 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 SELECT * FROM #work_to_do;
    OPEN partitions;

    — Цикл по секциям
    FETCH NEXT FROM partitions INTO @object_id, @index_id, @partition_number, @fragmentation_in_percent;
    WHILE @@FETCH_STATUS = 0
    BEGIN

    — Собираем имена объектов по ID
    SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name)
    FROM sys.objects AS o
    JOIN sys.schemas as s ON s.schema_id = o.schema_id
    WHERE o.object_id = @object_id;

    SELECT @indexname = QUOTENAME(name)
    FROM sys.indexes
    WHERE object_id = @object_id AND index_id = @index_id;

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

    — Если фрагментация менее или равна 30% тогда дефрагментация, иначе реиндексация
    IF @fragmentation_in_percent = 30.0

    —перестроение индекса
    SET @command = N’ALTER INDEX ‘ + @indexname + N’ ON ‘ + @schemaname + N’.’ + @objectname + N’ REBUILD WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, SORT_IN_TEMPDB = ON, ONLINE = ON, maxdop = 8 )’;

    IF @partition_number > 1
    SET @command = @command + N’ PARTITION=’ + CAST(@partition_number AS nvarchar(10));

    — Выполняем команду
    EXEC (@command1);
    EXEC (@command);
    EXEC (@command2);
    PRINT N’Index: object_id=’ + STR(@object_id) + ‘, index_id=’ + STR(@index_id) + ‘, fragmentation_in_percent=’ + STR(@fragmentation_in_percent);
    PRINT N’Executed: ‘ + @command;

    — Следующий элемент цикла
    FETCH NEXT FROM partitions INTO @object_id, @index_id, @partition_number, @fragmentation_in_percent;

    END;

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

    — Удаление временной таблицы
    DROP TABLE #work_to_do;

    GO

  5. Сергей говорит:

    —да что за фигня то)) вот кусок недостающего кода
    — Если фрагментация менее или равна 30% тогда дефрагментация, иначе реиндексация
    IF @fragmentation_in_percent = 30.0

    —перестроение индекса
    SET @command = N’ALTER INDEX ‘ + @indexname + N’ ON ‘ + @schemaname + N’.’ + @objectname + N’ REBUILD WITH (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON, SORT_IN_TEMPDB = ON, ONLINE = ON, maxdop = 8 )’;

    IF @partition_number > 1
    SET @command = @command + N’ PARTITION=’ + CAST(@partition_number AS nvarchar(10));

    — Выполняем команду
    EXEC (@command1);
    EXEC (@command);
    EXEC (@command2);
    PRINT N’Index: object_id=’ + STR(@object_id) + ‘, index_id=’ + STR(@index_id) + ‘, fragmentation_in_percent=’ + STR(@fragmentation_in_percent);
    PRINT N’Executed: ‘ + @command;

  6. сергей говорит:

    —какая-то фигня с сайтом. не знаю почему не вставлят несколько строчек. похоже, считает вредоносным кодом(

    — Если фрагментация менее или равна 30% тогда дефрагментация, иначе реиндексация
    IF @fragmentation_in_percent = 30.0

    —перестроение индекса

  7. Сергей говорит:

    Вот тут сделал тему про оптимизацию вашего скрипта. Все получилось, но комментарии и помощь приветствуются!
    http://www.gilev.ru/forum/viewtopic.php?f=15&t=2012&p=8603#p8603

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *