В практике разработчика 1С иногда встречается пугающая ситуация: отчет, построенный на виртуальных таблицах регистра накопления, показывает неверные данные (например, количество удваивается), хотя при детальном изучении регистратора в его движениях все корректно. Проанализируем, почему это происходит, как диагностировать проблему с помощью программного запроса и какими методами можно восстановить целостность базы данных.
Основная причина "странного" поведения регистра заключается в рассинхронизации между основной таблицей движений и таблицей итогов. Виртуальные таблицы 1С (такие как Обороты) работают по разным алгоритмам в зависимости от параметров:
Рассмотрим пример запроса, который позволяет наглядно увидеть это расхождение. Мы объединяем данные, полученные с детализацией до записи, и данные без детализации, чтобы сравнить их в одной таблице:
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.ДокументПродажи,
СУММА(ПродажиОбороты.КоличествоОборот) КАК КоличествоОборотПериод,
0 КАК КоличествоОборот
ПОМЕСТИТЬ ТаблицаПродаж
ИЗ
РегистрНакопления.Продажи.Обороты(&D1, &D2, Запись, ) КАК ПродажиОбороты
СГРУППИРОВАТЬ ПО
ПродажиОбороты.Номенклатура,
ПродажиОбороты.ДокументПродажи
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.ДокументПродажи,
0,
СУММА(ПродажиОбороты.КоличествоОборот)
ИЗ
РегистрНакопления.Продажи.Обороты(&D1, &D2, , ) КАК ПродажиОбороты
СГРУППИРОВАТЬ ПО
ПродажиОбороты.Номенклатура,
ПродажиОбороты.ДокументПродажи;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ТаблицаПродаж.Номенклатура,
ТаблицаПродаж.ДокументПродажи,
СУММА(ТаблицаПродаж.КоличествоОборотПериод) КАК КоличествоОборотПериод,
СУММА(ТаблицаПродаж.КоличествоОборот) КАК КоличествоОборот
ПОМЕСТИТЬ ТаблицаПродажГрупп
ИЗ
ТаблицаПродаж КАК ТаблицаПродаж
СГРУППИРОВАТЬ ПО
ТаблицаПродаж.Номенклатура,
ТаблицаПродаж.ДокументПродажи;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ТаблицаПродажГрупп.Номенклатура,
ТаблицаПродажГрупп.ДокументПродажи,
ТаблицаПродажГрупп.КоличествоОборотПериод,
ТаблицаПродажГрупп.КоличествоОборот
ИЗ
ТаблицаПродажГрупп КАК ТаблицаПродажГрупп
ГДЕ
ТаблицаПродажГрупп.КоличествоОборотПериод <> ТаблицаПродажГрупп.КоличествоОборот
Если этот запрос возвращает строки — значит, итоги вашего регистра "битые". Разберем причины, по которым это могло произойти.
Проанализируем основные технические факторы, приводящие к некорректным итогам:
РазделениеИтогов система создает дополнительные записи в таблицах итогов для борьбы с блокировками. В редких случаях при слиянии этих записей или при высоконагруженной записи могут возникать ошибки на уровне СУБД.rphost или обрыв связи с SQL-сервером, данные могут записаться в основную таблицу, но не обновиться в таблице агрегатов.Рассмотрим по шагам, как починить "нехорошее" поведение регистра.
Это самый надежный, но и самый длительный способ. Процедура полностью очищает таблицы итогов и заполняет их заново на основании физической таблицы движений. Выполнить это можно либо через конфигуратор (Тестирование и исправление — Пересчет итогов), либо программно:
РегистрыНакопления.Продажи.ПересчитатьИтоги();
Важный нюанс: Метод ПересчитатьИтогиЗаПериод() часто оказывается неэффективным для оборотных регистров, так как ошибка может сидеть в данных за очень старые периоды, которые все равно влияют на общие итоги. Если база большая, пересчет может занять несколько часов.
Если вам нужно ускорить процесс на большой базе, проанализируем альтернативный вариант. Отключение использования итогов физически удаляет (выполняет команду TRUNCATE на уровне SQL) таблицу итогов. При последующем включении система будет вынуждена создать и заполнить её с нуля.
// Отключаем использование итогов (таблица очищается)
РегистрыНакопления.Продажи.УстановитьИспользованиеИтогов(Ложь);
// Включаем обратно (начинается заполнение актуальными данными)
РегистрыНакопления.Продажи.УстановитьИспользованиеИтогов(Истина);
Этот метод часто работает быстрее стандартного пересчета, так как операции создания таблицы в СУБД эффективнее массового обновления строк (UPDATE).
Посмотрим на ситуацию со стороны системного администрирования. Если подобные проблемы возникают периодически, рекомендуется включить в план обслуживания базы данных (обычно выполняется ночью) операцию "Тестирование и исправление" с выбранным пунктом "Пересчет итогов". Это гарантирует, что к началу рабочего дня все агрегаты в базе будут актуальными.
Чтобы минимизировать риски в будущем, проанализируем следующие рекомендации:
Продажи не критичны блокировки (например, записи идут не постоянно), попробуйте отключить свойство Разделение итогов в конфигураторе. Это упростит структуру таблиц БД.Подведем итог: если вы заметили, что в отчетах "двоится" количество, первым делом проверьте данные запросом с периодичностью Запись. Если цифры сошлись с первичкой — смело планируйте полный пересчет итогов регистра, так как это единственный гарантированный способ вернуть системе корректное состояние.