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

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

При миграции информационной базы 1С:Предприятия 7.7 с формата файлов DBF на MS SQL Server стандартными средствами («Выгрузить данные» — «Загрузить данные») нередко возникает критическая ситуация: документы и справочники переносятся полностью, но на начало рабочего периода напрочь исчезают входящие остатки по регистрам накопления. Если посмотреть таблицы напрямую, выясняется, что в исходной DBF-базе остатки за прошлые годы есть, а в новой SQL-базе таблицы регистров содержат данные лишь с недавнего времени либо вовсе пусты. Разберем механику этой проблемы и рассмотрим рабочие способы её решения.

Анализ архитектуры: почему штатная выгрузка теряет итоги

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

  1. Таблица движений (префикс RA*): хранит детальные записи всех приходов и расходов, сформированных проведенными документами. Каждая строка намертво привязана к документу-регистратору.
  2. Таблица итогов (префикс RG*): хранит периодически рассчитанные входящие остатки на начало каждого месяца и на точку актуальности (ТА).

Штатный механизм выгрузки данных платформы (архив 1Cv7.DAT) устроен так, что таблицы RG* в архив не включаются вообще. С точки зрения разработчиков платформы, итоги являются производными данными. При загрузке архива в новую базу (хоть в SQL, хоть в чистую DBF) платформа автоматически пересчитывает таблицу RG* с нуля на основании строк из таблицы движений RA*.

Проблема возникает тогда, когда над базой ранее проводилась некорректная «ручная» срезка: предыдущие специалисты физически очистили старые записи движений в RA* для уменьшения размера файлов, а рассчитанные остатки просто оставили прямой записью в файле RG* без создания официального документа-регистратора. В исходной базе DBF такие «оторванные» остатки продолжают читаться до первого полного пересчета итогов, но при стандартной выгрузке/загрузке они безвозвратно теряются, так как в RA* записей нет и восстановить остатки платформе неоткуда.

Способ 1. Архитектурно правильное решение (Создание документа ввода остатков)

Самый надежный способ, гарантирующий, что база в SQL будет жить долго, а будущие регламентные операции и тестирование с исправлением не разрушат итоги, — вернуть остаткам легитимный документ-регистратор. Разберем этот процесс по шагам.

  1. Откроем исходную работоспособную DBF-базу.
  2. Создадим в конфигурации служебный документ (или используем готовые универсальные обработки-корректоры регистров). Документ должен иметь движения по требуемым регистрам накопления.
  3. Напишем обработку заполнения, которая считает остатки из текущих итогов на дату срезки (например, на 31.12.2015 23:59:59). Для каждого регистра выгрузим остатки по всем разрезам измерений и ресурсов.
  4. Заполним созданный документ строками движений с видом «Приход». Если записей много (десятки тысяч строк), обязательно разобьем их на пачки документов, так как табличная часть документов в 7.7 имеет технические ограничения.
  5. Проведем созданные документы датой ввода остатков. В результате в таблице RA* появятся реальные строки движений, привязанные к документу.
  6. Выполним стандартную выгрузку базы в файл 1Cv7.DAT и загрузим её в MS SQL Server. Платформа штатно рассчитает итоги, и входящие остатки будут полностью восстановлены.

Способ 2. Прямой перенос таблиц RG из DBF в SQL

Если сроки поджимают или структуру конфигурации категорически запрещено менять, можно перенести сформированные таблицы итогов RG* напрямую из файлов DBF в базу MS SQL Server. Однако важно помнить: любой последующий запуск тестирования и исправления с пересчетом итогов или сдвиг точки актуальности назад в такой базе сотрет эти данные.

Рассмотрим, как выглядит попытка загрузки через COM-соединение ADODB по одной строке, и почему она вызывает катастрофическое падение скорости:


ADOSoedinenie = New COMОбъект("ADODB.Connection");
Command = New COMObject("ADODB.Command");
// Выполнение одиночных вставок в цикле
Command.CommandText = "INSERT INTO [v77].[dbo].[RG1207] (PERIOD, SP1208, SP1209, SP1210) VALUES (Convert(datetime,'01/08/2016',103), '  LTK1  ', '  2N  OGM51  ', 0)";
Command.Execute();

При таком подходе таблица из 6–7 миллионов записей вставляется сутками. Причина проста: на каждую команду INSERT СУБД открывает неявную транзакцию, делает запись в журнал транзакций (LDF) и заново перестраивает дерево индексов таблицы.

Как ускорить прямую загрузку данных в MS SQL Server

Если мы выбираем путь прямой загрузки, оптимизируем работу с СУБД, применив следующие технические приемы:

  1. Пакетные транзакции (Batching): Никогда не отправляем команды по одной строке. Объединяем команды в транзакции по 10 000 – 50 000 строк. Это снизит нагрузку на дисковую подсистему и журнал транзакций в десятки раз.
  2. Отключение индексов: Перед загрузкой миллионов строк отключаем некластеризованные индексы целевой таблицы через команду СУБД ALTER INDEX [ИмяИндекса] ON [Таблица] DISABLE;. После завершения всей вставки перестраиваем их заново вызовом REBUILD.
  3. Модель восстановления: В свойствах базы данных MS SQL временно переключаем модель восстановления (Recovery Model) в режим Simple (Простая), чтобы исключить лавинообразный рост лога транзакций.
  4. Использование высокоскоростных механизмов вставки: Вместо одиночных INSERT используем утилиту bcp, T-SQL команду BULK INSERT, связные серверы (Linked Server через OLE DB к каталогу DBF) либо компонент SqlBulkCopy.

Также учитываем специфику типов данных: поле PERIOD в таблицах RG* на стороне SQL Server имеет тип DATETIME (всегда первое число месяца со временем 00:00:00.000), строковые идентификаторы (Base36) имеют фиксированную длину CHAR с выравниванием пробелами, а числовые поля строго соответствуют формату NUMERIC.

← На главную