Восстановление индексов СУБД

09.10.19

Задачи пользователя - Корректировка данных

Восстановление индексов СУБД на основе структуры хранения базы данных 1С.

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

"У нас ничего не работает!!"

"База тормозит!!"

Ну что могло случиться на выходных? Все работало и вдруг перестало.

Ознакомившись с работой пользователей, выяснил, что основная масса запросов идет к регистрам с распухшим (для текущей ситуации) количеством записей - четыре регистра накопления с количеством от 1,5 до 46 млн. записей.

Сразу подумал про индексы для этих регистров, т.к. база переработанная и регистры добавленные. Поскольку всех нюансов еще не знаю, т.к. стаж работы в данной организации без году неделя, открываю конфигуратор. Так и есть - ни одного индекса по полям, участвующим в отборах. Передав привет создателю данных объектов метаданных, добавляем индексы. После обновления конфигурации, ситуация несколько выравнивается и запросы к "пухлым" регистрам идут пошустрее, но тормозит уже все вокруг: прежние "быстрые" отчеты, проведение документов, стандартные функции с обращением к БД.

Ну и как вы наверное уже догадались, для большинства объектов базы 1С в СУБД физически не существовало индексов, что и показала нам MS SQL Studio. В связи с чем, это могло произойти так и не понял. Причем индексов не было на двух базах MSSQL. Есть подозрения, что базы входили в режим восстановления, возможно это и явилось причиной.

Первым пришедшим на ум решением, было достать описание метаданных (скрипт создания) из "живых" СУБД с наличием индексов и позаимствовав оттуда скрипты создания индексов просто выполнить их в "больных" базах. Но опыта работы с MS SQL не очень много, и данные потуги потерпели фиаско. В итоге пришла мысль создать скрипты создания индексов из структуры хранения базы данных 1С.

В связи с этим на свет и появился код для "Инструментов разработчика", коим и поспешил поделиться с сообществом.

 

//*********************************
// ОБЩИЕ ПЕРЕМЕННЫЕ
ИмяБазыСУБД = "MyBASE";
ВыводитьСтатусОперации = Истина;

// для получения только отсутствующих в СУБД
ТолькоОтсутствующиеВСУБД = Истина;
ИмяСервераСУБД = "MyServer";
ИмяПользователяСУБД = "sa";
ПарольПользователяСУБД = "MyPassword";
//*********************************

Состояние("Получаем структуру хранения базы данных...");
СХД= ПолучитьСтруктуруХраненияБазыДанных(,Истина); // по всем объектам, в терминах СУБД

Состояние("Заполняем таблицу данных для создания индексов...");

ТЗИнд = Новый ТаблицаЗначений;
ТЗИнд.Колонки.Добавить("ИмяИндекса");        					// имя индекса из СХД
ТЗИнд.Колонки.Добавить("ИмяТаблицы");        					// имя таблицы 1С
ТЗИнд.Колонки.Добавить("ИмяМетаданного"); 					// метаданные из СХД
ТЗИнд.Колонки.Добавить("ПоляИндекса");  						// таблица значений из СХД
ТЗИнд.Колонки.Добавить("ПоляИндексаСтрокой");  		// все поля собрали в строку
ТЗИнд.Колонки.Добавить("Кластеризованный"); 				// кластеризованный или нет
ТЗИнд.Колонки.Добавить("СтрокаСоздания"); 					// строка для создания индекса в СУБД

Для Каждого СтрокаСХД Из СХД Цикл
	Для Каждого СтрокаИндексаСХД Из СтрокаСХД.Индексы Цикл
		ИмяМетаданного = СтрокаСХД.ИмяТаблицыХранения;
		ИмяИндексаХранения = СтрокаИндексаСХД.ИмяИндексаХранения;
		
		СтрокаИнд = ТЗИнд.Добавить();
		СтрокаИнд.ИмяМетаданного = ИмяМетаданного;
		СтрокаИнд.ИмяИндекса = ИмяИндексаХранения;
		СтрокаИнд.ПоляИндекса = СтрокаИндексаСХД.Поля;
		СтрокаИнд.ИмяТаблицы = СтрокаСХД.ИмяТаблицы;
		
		// собрали поля индекса в строку
		ПоляИндексаСтрокой = "";
		Для Каждого СтрокаИмениПоля из СтрокаИнд.ПоляИндекса Цикл
			ПоляИндексаСтрокой = ПоляИндексаСтрокой+?(ПустаяСтрока(ПоляИндексаСтрокой),"",", ")+СтрокаИмениПоля.ИмяПоляХранения;
		КонецЦикла;	
		СтрокаИнд.ПоляИндексаСтрокой = ПоляИндексаСтрокой;
		 
		// вид индекса кластерный или нет - из копии оставшей СУБД или по имени индекса
		СтрокаИнд.Кластеризованный = 0;				
		Если Найти(ИмяИндексаХранения,"PK__") > 0 или                   // первичный для всех
				Найти(ИмяИндексаХранения,"_IntKeyInd") > 0 или 		 	// для табличных частей документов
				Найти(ИмяИндексаХранения,"_ByDataKey_") > 0  или     // 
				Найти(ИмяИндексаХранения,"_TRN") > 0 							// для регистров
				Тогда				
				СтрокаИнд.Кластеризованный = 1;				
				
		КонецЕсли;		
			
	КонецЦикла;	
	
КонецЦикла;	

// получим индексы из СУБД
СоответствиеИндексов = Новый Соответствие;
Если ТолькоОтсутствующиеВСУБД тогда
	Состояние("Получаем индексы СУБД ...");
	
	СтрокаСоединения = "Provider=SQLOLEDB; Data Source="""+ИмяСервераСУБД+"""; Initial Catalog="""+ИмяБазыСУБД+"""; User Id="""+ИмяПользователяСУБД+"""; Password="""+ПарольПользователяСУБД+"""";
	Соединение = Новый COMОбъект("ADODB.Connection");
	Соединение.ConnectionString = СтрокаСоединения;
	Соединение.Open();

	Команда = Новый COMОбъект("ADODB.Command");
	Команда.ActiveConnection = Соединение;
	Команда.CommandText = "select name, type from sys.indexes where type <> 0";
	Данные = Команда.Execute();

	Данные.MoveFirst();
	Пока НЕ Данные.EOF Цикл
		ИмяИндекса = Данные.Fields.Item(0).Value;
		СоответствиеИндексов.Вставить(ИмяИндекса,ИмяИндекса);
		Данные.MoveNext();
	КонецЦикла;	
КонецЕсли;

// собираем строку создания индекса на стороне СУБД
// https://docs.microsoft.com/ru-ru/sql/t-sql/statements/create-index-transact-sql?view=sql-server-2017
// Создавайте кластеризованные индексы до создания любых некластеризованных. 
// При создании кластеризованного индекса все существующие некластеризованные индексы таблицы перестраиваются.
ТЗИнд.Сортировать("ИмяТаблицы Возр,Кластеризованный Убыв");
КоличествоСтрок = ТЗИнд.Количество();
Ном =1;

Состояние("Получаем финальный скрипт...");
СтрокаСкрипта = "use "+ИмяБазыСУБД+" GO";
Для Каждого СтрокаИнд Из ТЗИнд Цикл
	    ИмяИндекса  = СтрокаИнд.ИмяИндекса;
		
		ИндексЕстьВСУБД = Ложь;
		Если ТолькоОтсутствующиеВСУБД тогда
			ИндексЕстьВСУБД = СоответствиеИндексов.Получить(ИмяИндекса) <> Неопределено;
		КонецЕсли;
		
		Если ИндексЕстьВСУБД тогда
			Продолжить;
		КонецЕсли;
		
		СтрокаСоздания = "";
		// статус операции для наглядности
		Если ВыводитьСтатусОперации тогда
			СтрокаСтатуса =  Строка(Ном)+" из "+Строка(КоличествоСтрок) + " ("+Формат(Ном*100/КоличествоСтрок,"ЧЦ=4; ЧДЦ=2; ЧГ=0")+"%)";
			СтрокаСоздания = "Print('"+СтрокаСтатуса +". "+СтрокаИнд.ИмяТаблицы+"')"+Символы.ПС; 			// выведем имя таблицы 1С
		КонецЕсли;	
		//--
		
		СтрокаСоздания = СтрокаСоздания +"CREATE UNIQUE " + ?(СтрокаИнд.Кластеризованный = 1," CLUSTERED ","")+ " INDEX "         		// имя индекса
										+ ИмяИндекса+Символы.ПС+" ON ["+ИмяБазыСУБД+"].dbo.["+СтрокаИнд.ИмяМетаданного+"] ("        // имя метаданного SQL
										+ СтрокаИнд.ПоляИндексаСтрокой +") "+ "WITH (DROP_EXISTING = OFF) "                                                                   // поля индекса
										+ "  ON [PRIMARY] "
										+Символы.ПС+"GO";									
		СтрокаИнд.СтрокаСоздания = СтрокаСоздания; 					
		
		СтрокаСкрипта = СтрокаСкрипта+?(ПустаяСтрока(СтрокаСкрипта),"", Символы.ПС)+ СтрокаСоздания;
		
		Ном = Ном + 1;
КонецЦикла;

// добавили в скрипт обновление статистики и чистку кэша
СтрокаСкрипта = СтрокаСкрипта + Символы.ПС
							+" EXEC sp_updatestats;"+Символы.ПС
							+ "DBCC FREEPROCCACHE";

 

Результат выполнения - строка, которую использовал в MS SQL Studio, чтобы отслеживать прогресс выполнения создания индексов.

 

UPD 1.

В код добавлена возможность создавать только отсутствующие в СУБД индексы. Для этого используем подключение ADO и анализ имеющихся в СУБД индексов.

Регулируется параметром "ТолькоОтсутствующиеВСУБД " в шапке кода.

См. также

Исправление в 1С:ЗУП/ЗКГУ ошибок по НДФЛ и взаиморасчетам с сотрудниками на начало расчетного года.

Корректировка данных Зарплата Платформа 1С v8.3 Сложные периодические расчеты 1С:Зарплата и кадры бюджетного учреждения 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет НДФЛ Платные (руб)

Обработка исправляет технические ошибки по НДФЛ, взаиморасчетам с сотрудниками в 1С:ЗУП (1С:ЗКГУ) на начало года. Фактически все ошибки, которые проявляются в ведомостях на выплату, расчетных листках, при заполнении ведомостей на выплату и отчетах 6-НДФЛ и т.д. нужно начинать исправлять с начала расчетного года. Это позволит быть уверенными, что после завершения расчетов предыдущего года, начали работать с «чистого листа» без ошибочных остатков.

4800 руб.

06.10.2023    2307    29    15    

33

Тестирование и исправление ключей аналитики ERP, УТ11, КА

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

Незаменимая обработка для сопровождения конфигураций: ERP, УТ, КА. Позволяет вычистить многие ошибки в ключах аналитики, в ключевых справочниках конфигурации.

3600 руб.

10.02.2017    106787    633    173    

675

Ускоренное проведение документов (x4), устранение ошибок 60/62 счетов и зачет авансов (Бухгалтерия 3.0)

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

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

14400 руб.

29.04.2020    27363    79    146    

59

Исправление ошибки закрытия месяца "Обнаружены ненулевые остатки по суммам при нулевом остатке по количеству в регистре себестоимости по организации". УТ 11.4,УТ 11.5, КА 2.4,КА 2.5, ERP 2.4, ERP 2.5, КА 2 Казахстан, Управление торговлей 3 для Казахстана

Закрытие периода Корректировка данных Платформа 1С v8.3 Оперативный учет 1С:Управление торговлей 11 Управленческий учет Платные (руб)

Закрытие месяца - важный процесс в современных конфигурациях, таких как УТ 11.4, УТ 11.5, КА 2.4, КА 2.5 ERP 2.4,ERP 2.5, КА 2 Казахстан, УТ 3 Казахстан регламентные операции влияют на расчет себестоимости, и ошибки в данном расчете не дают картины деятельности организации.

2400 руб.

27.10.2021    22314    299    35    

71

SALE! 20%

Заполнение документа "Корректировка регистров" произвольными данными

Закрытие периода Корректировка данных Платформа 1С v8.3 Система компоновки данных 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Управленческий учет Платные (руб)

Внешняя обработка, позволяющая произвольным образом заполнять документ "Корректировка регистров" Предназначена для использования в конфигурациях "Управление торговлей 11", "Управление небольшой фирмой", "ERP Управление предприятием", а также в других конфигурациях, в состав которых входит библиотека стандартных подсистем (БСП) версии 2.2+ и указанный выше документ.

2400 1920 руб.

13.07.2015    50160    171    29    

121
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. triviumfan 92 15.10.19 09:04 Сейчас в теме
ТиИ -> Реиндексация?
2. Pixar0000 18.10.19 14:52 Сейчас в теме
"собираем строку создания индекса на стороне СУБД"
профанация и бред
3. пользователь 31.07.22 17:10
Сообщение было скрыто модератором.
...
Оставьте свое сообщение