Реорганизация индексов базы данных MS SQL "Невозможно реорганизовать индекс"

1. tekit 09.11.22 11:35 Сейчас в теме
Приветствую вас заклинатели железа, направляю вам преинтереснейшую ситуёвину для разбора и помощи вашему слуге.

Проблема: После обновления платформы 8.3.20.1674->8.3.22.1603 сломалось автоматическое резервное копирование баз данных, созданное менеджером в SSMS 2012. При попытке реиндексации баз данных коих у нас не одна, ssms ругается на "Невозможно реорганизовать индекс "_Acc48_1" в таблице "_Acc48", поскольку отключена блокировка на уровне страницы." И так на 30к+ индексов. Во всех базах где произошло какое-то обновление/регламентное задание/бог его знает что ещё. В кратце, для реиндексации нужно чтобы все таблицы баз были с включенным параметром "allow_page_locks" или как описан в клиенте он "Блокировка страниц в памяти".

Что пробовал?:
· Гуглил. Не помогло.
· Доставать dt сувать обратно, индексы логично достаются и суются вместе с базой. Не помогло.
· Поднимал бэкап до обновления платформы в тест базу, смотрел что в индексах с нашим параметром. Там везде "ON". У нас после обновы в 30к "OFF".
· В небольших базах было по 1-2 индекса с флагом офф, проставлял там руками параметр в истину, запускал план бэкапа, реиндексация и сам бэкап проходили на ура. Сделал вывод, что выставив как-то параметр в 30к индексах я таки получу автобэкапирование, но не пойму причины возникновения отключения параметра. Можно утолкать кусок скрипта перед реиндексацией который будет ставить параметр в "ON". Костыль....
· Пробовал делать тестирование и исправление ошибок через конфигуратор. Не помогло.

Люди добрые:
Кто сталкивался с подобным? Подскажите как решали.
Кто сможет написать запрос который в автомате проставит флаг во всех индексах всех таблиц базы, буду очень признателен.
Конструкция
ALT ER   INDEX ALL ON <Table name>
SET (ALLOW_PAGE_LOCKS = ON)
GO
не помогает, так как во втором параметре нужна таблица, как туда указать все таблицы, не знаю, не могу, не умею.
mafnitofon; onetone; arkitekt; user1795406; thunder367; +5 Ответить
Найденные решения
8. splxgf 09.11.22 16:35 Сейчас в теме
(1)
как туда указать все таблицы, не знаю

USE имя базы
EXEC sp_MSforeachtable 'ALT ER   INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = ON)' 
GO

Проверьте такой вариант, имя таблицы автоматом подставляется вместо знака вопроса.
fuser; onetone; MaZaHacKa_13; arkitekt; Sley; maikl007; yaguarrr; +7 Ответить
Остальные ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
100. bardaknn 11.01.23 08:29 Сейчас в теме
(99) Да я просто мимо проходил.
Особенно смешно про 1Сные приседания))
101. srg123 05.02.23 10:51 Сейчас в теме
(96) Все норм. Все работает. Для тех кто в танке - пробелы лишние уберите в коде FR OM -> FROM и т.д.
(100) Бывает... )
102. alexis9 06.02.23 11:39 Сейчас в теме
Подскажите, пожалуйста.
Поставили платформу 8.3.22.ххх
По некоторым причинам пришлось сразу же откатиться на платформу 8.3.18
И там столкнолись с ошибкой при реиндексации. Судя по всему, реструктуризация БД не учла изменения в БД внесенные платформой 22.
Описаный здесь скрипт помог.
Но у меня вопрос.
Надо ли мне использовать после реиндексации второй скрипт для выключения блокировок?
Ведь сейчас у меня платформа 18, а не 22. А 1с внесла изменения в блокировки только на 22й платформе.
103. kiykomi 08.02.23 16:32 Сейчас в теме
Вот правильная конструкция, которая работает у меня:

До реорганизации индекса:
DECLARE @dbname nvarchar(128)
DECLARE @sql nvarchar(max)
DECLARE db_cursor CURSOR FOR
SEL ECT name FR OM sys.databases
WHERE name NOT IN ('master','tempdb','model','msdb')

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @dbname

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT @dbname
    SET @sql = 'USE [' + @dbname + '];' +
                'EXEC sp_MSforeachtable ''ALT ER   INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = ON)'';' +
                'EXEC sp_MSforeachtable ''ALT ER   INDEX ALL ON ? SET (ALLOW_ROW_LOCKS = ON)'''
    EXEC (@sql)
    PRINT 'Using database: ' + @dbname
    FETCH NEXT FROM db_cursor INTO @dbname
END

CLOSE db_cursor
DEALLOCATE db_cursor
Показать


И после:
DECLARE @dbname nvarchar(128)
DECLARE @sql nvarchar(max)
DECLARE db_cursor CURSOR FOR
SEL ECT name FROM sys.databases
WH ERE name NOT IN ('master','tempdb','model','msdb')

OPEN db_cursor
FETCH NEXT FR OM db_cursor INTO @dbname

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT @dbname
    SET @sql = 'USE [' + @dbname + '];' +
                'EXEC sp_MSforeachtable ''ALT ER   INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = OFF)'';' +
                'EXEC sp_MSforeachtable ''ALT ER   INDEX ALL ON ? SET (ALLOW_ROW_LOCKS = OFF)'''
    EXEC (@sql)
    PRINT 'Using database: ' + @dbname
    FETCH NEXT FR OM db_cursor INTO @dbname
END

CLOSE db_cursor
DEALLOCATE db_cursor
Показать


Всё отрабатывает отлично.
mfg-super; thunder367; +2 Ответить
106. mfg-super 12.03.23 20:02 Сейчас в теме
(103)
А Вам не кажется, что в скрипте После должно быть так: "ALLOW_PAGE_LOCKS = OFF" и "ALLOW_ROW_LOCKS = ON"?

На ИТС такая информация по этому вопросу:
Важно! Начиная с версии платформы 8.3.22 необходимо выполнять дефрагментацию индексов по следующему алгоритму:
До дефрагментации индекса необходимо включить страничные блокировки. Пример команды: ALT ER INDEX index_name ON table_name SET (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON);
Выполнить дефрагментацию.
Обратно выключить страничные блокировки. Пример команды: ALT ER INDEX index_name ON table_name SET (ALLOW_PAGE_LOCKS = OFF, ALLOW_ROW_LOCKS = ON);
104. kiykomi 08.02.23 16:34 Сейчас в теме
Здесь не нужно указывать базы, просто автоматически берутся все БД, кроме системных и даже обходит ошибку в именах БД со знаком "-" (тире) в имени благодаря квадратным скобкам.
Просто юзайте на здоровье.
105. kiykomi 09.02.23 10:46 Сейчас в теме
Апдейт - чтобы пропускало базы со статусом "Вне сети" добавьте AND state = 0 в конструкцию WHERE name NOT IN ('master','tempdb','model','msdb'), вот так вот:

WHERE name NOT IN ('master','tempdb','model','msdb') AND state = 0
107. TormDV 13.03.23 08:17 Сейчас в теме
Кто-нибудь тестил отключение-включение страничных блокировок сколько времени занимает? Если допустим терабайтная база на сервере крутится или 30-40 баз поменьше... Какую нагрузку включение-отключение создает на сервер?
З.Ы. Сам не проверял, возможно там доли секунды и никаких подводных камней, но вдруг..
108. ESPakhomov 06.04.23 14:33 Сейчас в теме
На сколько вообще корректно использовать:
ALT ER INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = ON)
ALT ER INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = OFF)
Если посмотреть индексы до этих манипуляций, то есть индексы у которых изначально ALLOW_PAGE_LOCKS = ON и этими действиями по итогу изменяем их на ALLOW_PAGE_LOCKS = OFF. например:
Прикрепленные файлы:
109. LuMp1ck 08.04.23 06:27 Сейчас в теме
Дай Вам Бог всем здоровья, и долгих лет жизни!

Тоже столкнулся, платформа v8.3.22.1750 + MS SQL 2012

Всё было настроено и всё работало ... но потом ... но потом перестало ))
В результате добавив в план обслуживания шаги на нужных этапах, всё заработало снова!

Единственной, там выше уточняли, что запросе изначально была ошибка ALTER было написано через пробел, поэтому запрос не отрабатывал

USE ERP
EXEC sp_MSforeachtable 'ALT ER   INDEX ALL ON ? SET (ALLOW_PAGE_LOCKS = OFF)'
EXEC sp_MSforeachtable 'ALT ER   INDEX ALL ON ? SET (ALLOW_ROW_LOCKS= ON)'
GO
Прикрепленные файлы:
Anvarich; user1300601; +2 Ответить
110. MDR_Tiger 11.04.23 11:20 Сейчас в теме
Использую такой код для обслуживания индексов в MS SQL 2016:
DECLARE @Base_Name nvarchar(100);
DECLARE @Base_id int;
-- Обрабатываются все пользовательские базы данных в оперативном режиме
DECLARE Bases CURSOR FOR SEL ECT database_id FR OM sys.databases where database_id > 4 and state_desc = 'ONLINE';
-- Обрабатываются только нужные пользовательские базы данных в оперативном режиме
-- DECLARE Bases CURSOR FOR SEL ECT database_id FR OM sys.databases where database_id in (5,6,7,8) and state_desc = 'ONLINE';

OPEN Bases;
FETCH NEXT FR OM Bases INTO @Base_id;
WHILE @@FETCH_STATUS = 0
BEGIN  
-- Отбор таблиц и индексов с помощью системного представления sys.dm_db_index_physical_stats
-- Отбор только тех объектов которые являются индексами (index_id > 0), 
-- фрагментация которых более 10% и количество страниц в индексе более 128
Sel ect @Base_Name = DB_NAME(@Base_id)

PRINT @base_Name;

Exec ('Use ' + @base_Name + '
SET NOCOUNT ON; -- отключаем вывод количества возвращаемых строк, это несколько ускорит обработку
DECLARE @objectid int; -- ID объекта
DECLARE @indexid int; -- ID индекса
DECLARE @partitioncount bigint; -- количество секций если индекс секционирован
DECLARE @schemaname nvarchar(130); -- имя схемы в которой находится таблица
DECLARE @objectname nvarchar(130); -- имя таблицы 
DECLARE @indexname nvarchar(130); -- имя индекса
DECLARE @partitionnum bigint; -- номер секции
DECLARE @frag float; -- процент фрагментации индекса
DECLARE @allow_page_locks int; -- признак включенности блокировки на уровне страниц
DECLARE @command nvarchar(4000); -- инструкция T-SQL для дефрагментации либо ренидексации
	SEL ECT
		IndexStats.object_id AS objectid,
		IndexStats.index_id AS indexid,
		IndexStats.partition_number AS partitionnum,
		IndexStats.avg_fragmentation_in_percent AS frag,
		AllIndexes.allow_page_locks as allow_page_locks
	INTO #work_to_do
	FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, ''LIMITED'') AS IndexStats
	INNER JOIN sys.indexes AS AllIndexes
		ON AllIndexes.index_id = IndexStats.index_id
		AND AllIndexes.object_id = IndexStats.object_id
		AND IndexStats.avg_fragmentation_in_percent > 10.0
		AND IndexStats.index_id > 0
		AND IndexStats.page_count > 128;

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

	-- Открытие курсора
	OPEN partitions;
	-- Цикл по секциям
	WHILE (1=1)
		BEGIN;
			FETCH NEXT
			   FROM partitions
			   INTO @objectid, @indexid, @partitionnum, @frag, @allow_page_locks;

			IF @@FETCH_STATUS < 0 BREAK;
		
	-- Собираем имена объектов по ID		
			SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name)
			FR OM sys.objects AS o
			JOIN sys.schemas as s ON s.schema_id = o.schema_id
			WH ERE o.object_id = @objectid;
			SELECT @indexname = QUOTENAME(name)
			FR OM sys.indexes
			WH ERE  object_id = @objectid AND index_id = @indexid;
			SELECT @partitioncount = count (*)
			FR OM sys.partitions
			WH ERE object_id = @objectid AND index_id = @indexid;

	-- Если фрагментация менее или равна 30% тогда дефрагментация, иначе реиндексация
			IF @frag <= 30.0
				SET @command = N''ALT ER   INDEX '' + @indexname + N'' ON '' + @schemaname + N''.'' + @objectname + N'' REORGANIZE'';
			IF @frag > 30.0
				SET @command = N''ALT ER   INDEX '' + @indexname + N'' ON '' + @schemaname + N''.'' + @objectname + N'' REBUILD'';
			IF @partitioncount > 1
				SET @command = @command + N'' PARTITION='' + CAST(@partitionnum AS nvarchar(10));
			
	-- Если реиндексация, то для ускорения добавляем параметры использования TEMPDB(имеет смысл только если TempDB на отдельном физ. диске) и многопроцессорной обработки 
			IF @frag > 30.0
				SET @command = @command + N'' WITH (SORT_IN_TEMPDB = ON, MAXDOP = 0)'';
			
	-- Принудительное включение блокировки индекса на уровне страницы и её отключение, если блокировка была изначально выключена (для платформы 1С 8.3.22.х)
			IF @allow_page_locks = 0
				BEGIN
					SET @command = N''ALT ER   INDEX '' + @indexname + N'' ON '' + @schemaname + N''.'' + @objectname + N'' SET (ALLOW_PAGE_LOCKS = ON)'' + char(10) + @command;
					SET @command = @command + char(10) + N''ALT ER   INDEX '' + @indexname + N'' ON '' + @schemaname + N''.'' + @objectname + N'' SET (ALLOW_PAGE_LOCKS = OFF)'';
				END

			EXEC (@command);
			PRINT N''Executed: '' + @command;
		END;

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

	-- Удаление временной таблицы
	DR OP   TABLE #work_to_do;')
	FETCH NEXT FR OM Bases INTO @Base_id;
END;
CLOSE Bases;
DEALLOCATE Bases;
GO
Показать
fatman78; LineykaSBK; +2 Ответить
112. LineykaSBK 5 25.04.23 22:33 Сейчас в теме
(110)
Спасибо, вроде работает на sql 2019
113. fatman78 16 23.05.23 20:39 Сейчас в теме
(110)
INTO


Прикрепил этот скрипт в виде файла. на MS SQL 2017 с 1С 8.3.22 отлично работает.
Прикрепленные файлы:
SQLQuery_Rebuild_Reindex.sql
114. Vstur 26.05.23 14:29 Сейчас в теме
При откате с 22 платформы на более ранние, достаточно выгрузить в dt и загрузить обратно.
Тогда проблема проблема уйдет
115. oleg-x 26 01.06.23 14:07 Сейчас в теме
В июне ЗУП и в августе БУХ планируют поднять режим совместимости и минимальную версию платформы до 8.3.22
И я так понимаю на текущий момент проблема с индексами так же и осталась?
116. TormDV 01.06.23 14:36 Сейчас в теме
(115) Это не проблема, а фича. Считается, что так лучше производительность. Не завидую тем, кто на 3.1.25 ветке ЗУПа сидит. Про 8.3.23 версию платформы сегодня тема была, что в последнем релизе ерп проблемы в связи с наименование переменных и объектов платформы. Зато, возможно не будет сложного выбора, на какой платформе сидеть 8.3.17, 19 или 23...
117. oleg-x 26 01.06.23 14:38 Сейчас в теме
(116) Возможно то и лучше, только вот что делать тем, кто не в теме, как корректно работать с этой новой фичей :-(
118. TormDV 01.06.23 14:49 Сейчас в теме
(117) Методом научного тыка) В идеале на тестовом сервере платформу развернуть, и пару баз попробовать обслужить. Где завалится - использовать скрипты, что 1с сами предлагают или хоть из этой темы. Или, на крайняк, на боевом сервере, если вариантов нет. После обновления платформы тестовую базу небольшую развернуть, и для нее план обслуживания сделать на основании имеющегося, но с учетом индексов. Без реиндексации, конечно, плохо, за денек-другой, неделю глобально с базами ничего плохого не должно случиться.
З.Ы. Мы сами еще не переходили на новую платформу, только предстоит, вот и советы такие.
З.Ы.Ы. Да и сейчас много похожих тем будут создавать, сообщество поможет))
Оставьте свое сообщение
Вакансии
Программист/тестировщик
Москва
зарплата от 130 000 руб. до 150 000 руб.
Полный день

Ведущий разработчик 1С / Team lead отдела разработки 1С
Москва
зарплата от 300 000 руб. до 300 000 руб.
Полный день

Программист 1С
Москва
зарплата от 130 000 руб. до 150 000 руб.
Полный день

Бизнес-аналитик
Москва
зарплата от 130 000 руб. до 150 000 руб.
Полный день

Аналитик-архитектор 1С ЕРП (управленческого учета)
Москва
зарплата от 300 000 руб. до 300 000 руб.
Полный день