Почему перепроведение документов в 1С 7.7 на SQL работает значительно медленнее, чем в DBF, и как это ускорить?

Программист 1С v7.7 Управленческий учет IT и автоматизация бизнеса
← На главную

Перевод информационных баз 1С:Предприятия 7.7 с файловой модели (DBF) на реляционную СУБД (MS SQL Server) часто приводит к неожиданному результату: групповое перепроведение документов или проведение задним числом замедляется в 3–5 раз и более. При этом аппаратные ресурсы мощного сервера (процессор, объем оперативной памяти, дисковые массивы) остаются практически незагруженными. Разберем по шагам, почему возникает эта просадка, в чем заключаются фундаментальные различия работы двух движков и как исправить ситуацию без масштабного переписывания конфигурации.

Выясним причины низкой скорости штатного перепроведения на MS SQL

Чтобы понять природу замедления, проанализируем, как платформа 1С 7.7 взаимодействует с данными в обоих режимах:

  1. Синхронная запись журнала транзакций (WAL) в MS SQL. В файловом режиме (DBF) операционная система сбрасывает данные в кэш оперативной памяти асинхронно, мгновенно возвращая управление программе. В СУБД MS SQL Server для соблюдения принципов ACID при закрытии транзакции команда COMMIT TRAN обязана физически зафиксировать запись из буфера в лог-файл (.ldf). Поскольку при проведении каждого документа 1С открывает и закрывает отдельную транзакцию, дисковая подсистема выполняет тысячи одиночных синхронных операций ввода-вывода с ожиданием ответа.
  2. Построчная обработка (RBAR) и накладные расходы ODBC. Платформа 7.7 разрабатывалась под навигационную (ISAM) модель доступа. Штатные механизмы регистров при проведении выполняют не единый пакетный расчет на стороне сервера, а множество последовательных одиночных обращений к таблицам через интерфейс ODBC. Для файловой базы эти обращения происходят внутри памяти одного процесса, а для SQL каждое обращение сопряжено с межпроцессным или сетевым взаимодействием.
  3. Специфика метода ВыгрузитьИтоги() и временного расчета. Если документ проводится задним числом относительно точки актуальности (ТА), платформа инициирует временный расчет итогов. Если в регистрах накоплено огромное количество незакрытых остатков («хвостов»), платформа считывает гигантские объемы данных из таблицы итогов, выполняя фильтрацию на клиенте.

Проанализируем архитектуру регистров: незакрытые остатки

Главная практическая причина резкого падения производительности ВыгрузитьИтоги() — раздутая таблица итогов регистров. Рассмотрим механизм ее деградации. Регистр остатков хранит в таблице итогов срез по уникальным комбинациям всех измерений. Если в конфигурации допущена логическая ошибка, при которой приход пишется с одним набором измерений, а расход — с частично пустыми значениями или другими реквизитами, нулевой остаток не схлопывается.

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

Для исправления ситуации выполним следующие действия:

  1. Аудит измерений регистров. Проверим все документы, формирующие движения по проблемным регистрам. Измерения не должны оставаться незаполненными или содержать избыточную детализацию (например, уникальные номера заявок или временные статусы, которые никогда не списываются в ноль).
  2. Своевременное снятие зависших резервов и заказов. Если в компании используются предварительные заказы или бронирование, необходимо внедрить регламентный механизм их автоматического закрытия, чтобы они не увеличивали объем таблицы итогов на будущие расчетные периоды.
  3. Удаление фильтров по объекту СписокЗначений. Транслятор 1С 7.7 при использовании сложных условий и списков значений генерирует громоздкие предикаты для SQL, которые часто приводят к полному сканированию индекса. Значительно быстрее выгрузить итоги только по основным жестким фильтрам (или по регистру в целом), а окончательную выборку производить уже в объекте ТаблицаЗначений средствами встроенного языка.

Пакетное объединение транзакций при перепроведении

Для минимизации задержек на синхронную фиксацию журнала транзакций при групповой обработке документов применим группировку транзакций. Если объединять проведение документов в пакеты (например, по 50–100 документов в одной транзакции), количество операций сброса буфера журнала транзакций на диск снизится в десятки раз.

Посмотрим на пример организации пакетного перепроведения в коде внешней обработки:


КоличествоВПакете = 100;
Счетчик = 0;
ВТранзакции = 0;

ВыборкаДокументов = СоздатьОбъект("Документ");
ВыборкаДокументов.ВыбратьДокументы(ДатаНачала, ДатаКонца);

Пока ВыборкаДокументов.ПолучитьДокумент() = 1 Цикл
    Если ВТранзакции = 0 Тогда
        НачатьТранзакцию();
        ВТранзакции = 1;
    КонецЕсли;
    
    Если ВыборкаДокументов.Проведен() = 1 Тогда
        ВыборкаДокументов.Провести();
        Счетчик = Счетчик + 1;
    КонецЕсли;
    
    Если (Счетчик % КоличествоВПакете) = 0 Тогда
        ЗафиксироватьТранзакцию();
        ВТранзакции = 0;
    КонецЕсли;
КонецЦикла;

Если ВТранзакции = 1 Тогда
    ЗафиксироватьТранзакцию();
КонецЕсли;

Настройка экземпляра MS SQL Server и подключения

Корректная настройка параметров СУБД позволяет нивелировать устаревшие алгоритмы генерации запросов платформы 1С 7.7:

  1. Использование протокола Shared Memory. Если сервер 1С (терминальный сервер) и служба SQL Server установлены в рамках одной операционной системы, подключение необходимо настраивать не через TCP/IP, а через протокол Shared Memory. Для этого в строке подключения или утилите настройки клиента указывается имя сервера (local) или точка .. Это полностью исключает накладные расходы стека TCP/IP.
  2. Ограничение параллелизма (MAXDOP = 1). Для экземпляра SQL Server зададим параметр Max Degree of Parallelism = 1. Одиночные запросы платформы 7.7 просты по структуре, и попытка оптимизатора SQL распараллелить их выполнение тратит ресурсы процессора на синхронизацию потоков и приводит к взаимным блокировкам.
  3. Простая модель восстановления (Simple Recovery Model). На время выполнения массовых регламентных перепроведений имеет смысл переводить базу данных в режим Simple, чтобы избежать лавинообразного роста размера файла .ldf.

Различие сортировки в DBF и SQL: справочники

Нередко при миграции на SQL возникает ситуация, когда список справочника при включении сортировки по реквизиту упорядочивается иначе, чем в DBF: вместо сортировки «Реквизит + Наименование» данные выводятся как «Реквизит + Код».

Выясним причину: в DBF-файле индексный ключ строится как связка реквизита с наименованием. В SQL-версии платформа 1С 7.7 для обеспечения уникальности некластеризованного индекса автоматически добавляет в конец индексного ключа поле внутреннего идентификатора ID (или код элемента). Соответственно, СУБД выполняет сортировку по построенному индексу.

Штатный метод Сортировка(<Способ>, <Разрешение>) принимает только одно поле. Чтобы вернуть правильный порядок отображения строк на SQL-базе, создадим в метаданных справочника служебный строковый реквизит, включим для него признак «Сортировка» и при записи элемента будем программно формировать его значение:


Процедура ПриЗаписи()
    // Заполняем служебное поле для корректной составной сортировки
    СлужебнаяСортировка = СокрЛП(Строка(РеквизитСортировки)) + "_" + СокрЛП(Наименование);
КонецПроцедуры

После заполнения этого реквизита достаточно вызывать метод Сортировка("СлужебнаяСортировка", 1), чтобы получить предсказуемый и корректный порядок строк на MS SQL Server.

← На главную