Перевод информационных баз 1С:Предприятия 7.7 с файловой модели (DBF) на реляционную СУБД (MS SQL Server) часто приводит к неожиданному результату: групповое перепроведение документов или проведение задним числом замедляется в 3–5 раз и более. При этом аппаратные ресурсы мощного сервера (процессор, объем оперативной памяти, дисковые массивы) остаются практически незагруженными. Разберем по шагам, почему возникает эта просадка, в чем заключаются фундаментальные различия работы двух движков и как исправить ситуацию без масштабного переписывания конфигурации.
Чтобы понять природу замедления, проанализируем, как платформа 1С 7.7 взаимодействует с данными в обоих режимах:
COMMIT TRAN обязана физически зафиксировать запись из буфера в лог-файл (.ldf). Поскольку при проведении каждого документа 1С открывает и закрывает отдельную транзакцию, дисковая подсистема выполняет тысячи одиночных синхронных операций ввода-вывода с ожиданием ответа.ВыгрузитьИтоги() и временного расчета. Если документ проводится задним числом относительно точки актуальности (ТА), платформа инициирует временный расчет итогов. Если в регистрах накоплено огромное количество незакрытых остатков («хвостов»), платформа считывает гигантские объемы данных из таблицы итогов, выполняя фильтрацию на клиенте.Главная практическая причина резкого падения производительности ВыгрузитьИтоги() — раздутая таблица итогов регистров. Рассмотрим механизм ее деградации. Регистр остатков хранит в таблице итогов срез по уникальным комбинациям всех измерений. Если в конфигурации допущена логическая ошибка, при которой приход пишется с одним набором измерений, а расход — с частично пустыми значениями или другими реквизитами, нулевой остаток не схлопывается.
Вместо удаления закрытой записи в таблице итогов накапливаются взаимно компенсирующие строки (например, +10 шт. по одной аналитике и -10 шт. по другой). В результате при вызове метода ВыгрузитьИтоги() сервер вынужден обрабатывать миллионы записей вместо нескольких тысяч актуальных остатков.
Для исправления ситуации выполним следующие действия:
СписокЗначений. Транслятор 1С 7.7 при использовании сложных условий и списков значений генерирует громоздкие предикаты для SQL, которые часто приводят к полному сканированию индекса. Значительно быстрее выгрузить итоги только по основным жестким фильтрам (или по регистру в целом), а окончательную выборку производить уже в объекте ТаблицаЗначений средствами встроенного языка.Для минимизации задержек на синхронную фиксацию журнала транзакций при групповой обработке документов применим группировку транзакций. Если объединять проведение документов в пакеты (например, по 50–100 документов в одной транзакции), количество операций сброса буфера журнала транзакций на диск снизится в десятки раз.
Посмотрим на пример организации пакетного перепроведения в коде внешней обработки:
КоличествоВПакете = 100;
Счетчик = 0;
ВТранзакции = 0;
ВыборкаДокументов = СоздатьОбъект("Документ");
ВыборкаДокументов.ВыбратьДокументы(ДатаНачала, ДатаКонца);
Пока ВыборкаДокументов.ПолучитьДокумент() = 1 Цикл
Если ВТранзакции = 0 Тогда
НачатьТранзакцию();
ВТранзакции = 1;
КонецЕсли;
Если ВыборкаДокументов.Проведен() = 1 Тогда
ВыборкаДокументов.Провести();
Счетчик = Счетчик + 1;
КонецЕсли;
Если (Счетчик % КоличествоВПакете) = 0 Тогда
ЗафиксироватьТранзакцию();
ВТранзакции = 0;
КонецЕсли;
КонецЦикла;
Если ВТранзакции = 1 Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
Корректная настройка параметров СУБД позволяет нивелировать устаревшие алгоритмы генерации запросов платформы 1С 7.7:
(local) или точка .. Это полностью исключает накладные расходы стека TCP/IP.Max Degree of Parallelism = 1. Одиночные запросы платформы 7.7 просты по структуре, и попытка оптимизатора SQL распараллелить их выполнение тратит ресурсы процессора на синхронизацию потоков и приводит к взаимным блокировкам.Simple, чтобы избежать лавинообразного роста размера файла .ldf.Нередко при миграции на SQL возникает ситуация, когда список справочника при включении сортировки по реквизиту упорядочивается иначе, чем в DBF: вместо сортировки «Реквизит + Наименование» данные выводятся как «Реквизит + Код».
Выясним причину: в DBF-файле индексный ключ строится как связка реквизита с наименованием. В SQL-версии платформа 1С 7.7 для обеспечения уникальности некластеризованного индекса автоматически добавляет в конец индексного ключа поле внутреннего идентификатора ID (или код элемента). Соответственно, СУБД выполняет сортировку по построенному индексу.
Штатный метод Сортировка(<Способ>, <Разрешение>) принимает только одно поле. Чтобы вернуть правильный порядок отображения строк на SQL-базе, создадим в метаданных справочника служебный строковый реквизит, включим для него признак «Сортировка» и при записи элемента будем программно формировать его значение:
Процедура ПриЗаписи()
// Заполняем служебное поле для корректной составной сортировки
СлужебнаяСортировка = СокрЛП(Строка(РеквизитСортировки)) + "_" + СокрЛП(Наименование);
КонецПроцедуры
После заполнения этого реквизита достаточно вызывать метод Сортировка("СлужебнаяСортировка", 1), чтобы получить предсказуемый и корректный порядок строк на MS SQL Server.