Почему задваиваются данные в запросе к оборотному регистру накопления при использовании периодичности «Авто»?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие 8 программисты часто сталкиваются с ситуацией, когда проверенный временем запрос внезапно начинает возвращать некорректные данные, а именно — удваивать или даже утраивать показатели. Рассмотрим типичный сценарий: есть оборотный регистр накопления, к которому обращается запрос для получения данных за определенный период. При использовании периодичности Авто данные двоятся, но если сменить периодичность на Регистратор, цифры становятся верными. Разберем подробно, почему это происходит и как правильно решить данную проблему.

Анализируем исходную ситуацию и структуру запроса

Проанализируем пример запроса, который вызывает подозрения. В нем используется обращение к виртуальной таблице Обороты регистра накопления:


ВЫБРАТЬ 
    НашРегистрОбороты.Номенклатура,
    НашРегистрОбороты.ХарактеристикаНоменклатуры,
    НашРегистрОбороты.КоличествоОборот КАК Количество
ИЗ
    РегистрНакопления.НашРегистр.Обороты(
            &НачалоПериода,
            &КонецПериода,
            авто,
            Параметр = &Параметр
                И Категория = ЗНАЧЕНИЕ(Перечисление.Параметры.Параметр)
                И Операция = ЗНАЧЕНИЕ(Перечисление.Параметры.Параметр1)) КАК НашРегистрОбороты

На первый взгляд, запрос составлен абсолютно корректно. Параметр периодичности авто является стандартным и часто используемым. Однако именно здесь кроется корень проблемы. Чтобы понять причину задвоения, нам нужно заглянуть "под капот" платформы и выяснить, как 1С работает с виртуальными таблицами.

Различие в работе виртуальных таблиц в зависимости от периодичности

Выясним, чем отличается поведение системы при разных настройках периодичности:

  1. Периодичность «Регистратор» или «Запись»: В этом режиме система вынуждена обращаться напрямую к основной физической таблице движений регистра. Она суммирует записи документов "на лету". Поскольку записи в основной таблице обычно корректны, запрос возвращает правильный результат.
  2. Периодичность «Авто», «Период» (День, Месяц и т.д.) или отсутствие периодичности: В этих случаях система старается оптимизировать выполнение запроса. Вместо того чтобы сканировать миллионы строк в таблице движений, она обращается к предварительно рассчитанным таблицам итогов. Эти таблицы хранят уже агрегированные данные, что значительно ускоряет работу.

Если данные в таблицах итогов по какой-то причине "разошлись" с реальными движениями документов, мы получаем неверный результат. Задвоение — это классический признак того, что таблица итогов содержит "мусорные" записи или ошибки суммирования.

Техническая причина: Механизм разделения итогов

Проанализируем, почему в таблице итогов могут появиться лишние данные. Одной из частых причин является включенное свойство регистра «Разделение итогов». Этот механизм позволяет нескольким пользователям одновременно записывать данные в регистр по одним и тем же измерениям (например, по одной номенклатуре) без блокировок. Для этого система создает несколько физических записей в таблице итогов для одной и той же комбинации измерений. При чтении запросом 1С должна их суммировать. Если в структуре базы данных происходит сбой (аварийное завершение транзакции, ошибки СУБД), эти записи могут начать обрабатываться некорректно, выдавая кратный результат.

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

Решение проблемы: Пересчет итогов

Единственным правильным решением в данной ситуации является приведение таблиц итогов в соответствие с таблицами движений. Рассмотрим, как это сделать.

Способ 1: Использование Конфигуратора

Это самый простой и надежный метод. Нам необходимо выполнить процедуру «Тестирование и исправление» (ТиИ):

  1. Запустим базу в режиме «Конфигуратор».
  2. Перейдем в меню «Администрирование» — «Тестирование и исправление».
  3. Установим флажок только на пункте «Пересчет итогов».
  4. Нажмем «Выполнить».

Система полностью очистит таблицы итогов и сформирует их заново на основании записей в таблицах движений документов.

Способ 2: Программный пересчет в режиме «Предприятие»

Иногда нет возможности выгнать всех пользователей из базы для монопольного доступа. В этом случае мы можем инициировать пересчет итогов программно с помощью встроенного языка. Для этого используется объект РегистрыНакопленияManager.

Рассмотрим пример кода для обработки:


// Выключаем использование итогов, что может привести к их очистке
РегистрыНакопления.НашРегистр.УстановитьИспользованиеИтогов(Ложь);

// Включаем обратно - система инициирует полный пересчет
РегистрыНакопления.НашРегистр.УстановитьИспользованиеИтогов(Истина);

// Можно также выполнить пересчет за конкретный период
РегистрыНакопления.НашРегистр.ПересчитатьИтоги(НачалоГода(ТекущаяДата()), КонецГода(ТекущаяДата()));

Важно: Программный пересчет в активной базе может вызвать серьезную нагрузку на сервер и СУБД. Рекомендуется выполнять такие процедуры в периоды минимальной активности пользователей.

Профилактика и регламентное обслуживание

Разберем, как избежать подобных проблем в будущем. Пересчет итогов не должен быть экстренной мерой. В крупных системах это обязательная регламентная процедура.

  1. Регулярное обслуживание: Рекомендуется выполнять полный пересчет итогов хотя бы раз в месяц. Это не только исправляет возможные ошибки, но и удаляет "пустые" записи (с нулевыми остатками), что ускоряет работу запросов.
  2. Обслуживание СУБД: Если используется клиент-серверный вариант (SQL), необходимо настроить планы обслуживания: обновление статистик и дефрагментацию индексов. Иногда "кривой" план запроса SQL-сервера может приводить к тому, что он выбирает неоптимальные таблицы для чтения.
  3. Отказ от динамического обновления: Хотя связь не всегда очевидна, динамическое обновление конфигурации («демонское обновление») часто приводит к кэшированию старых структур таблиц и планов запросов, что провоцирует ошибки в виртуальных таблицах.

Подводя итог, отметим: если вы видите задвоение данных в виртуальных таблицах 1С, первым делом проверьте актуальность и целостность итогов. В 99% случаев Пересчет итогов решит проблему без необходимости менять логику самих запросов.

← На главную