Почему запрос выдает разные данные в рабочей базе и как оптимизировать тяжелый бухгалтерский отчет

Программист 1С v8.3 (Обычные формы) Бухгалтерский учет
← На главную

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

Выясняем причины нестабильности данных

Первым делом разберем ситуацию, когда запрос выполняется крайне долго (например, около часа). В этом случае в рабочей базе на результат начинают влиять внешние факторы, которые отсутствуют в копии. Рассмотрим основные причины:

  1. Уровень изоляции транзакций. Если ваш запрос работает долго, он может сталкиваться с эффектом «фантомного чтения» или «несогласованного анализа». В 1С по умолчанию используется уровень Read Committed. Пока ваш запрос целый час «гуляет» по таблицам, другие пользователи проводят документы. Несмотря на заверения методистов, система может делать автоматические корректировки или закрытие месяца, что меняет итоги в процессе выполнения вашего запроса.
  2. Виртуальные таблицы и итоги. Виртуальная таблица ОборотыДтКт — одна из самых ресурсоемких. Она не существует физически, а собирается СУБД в момент обращения. Если в процессе этого «сбора» происходит обновление итогов или запись в регистр, результат может варьироваться.
  3. Разделение итогов. В современных конфигурациях включен режим разделения итогов. При высокой интенсивности записи данные в физических таблицах итогов могут временно находиться в разных записях с разными разделителями, что при определенных условиях и длинных запросах может вносить погрешность.

Важный вывод: Любой запрос, работающий более нескольких минут в транзакционной базе, потенциально нестабилен. Единственный верный способ борьбы с этим — кардинальное ускорение кода.

Анализируем и оптимизируем структуру запроса

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


// Неоптимальный подход: 
// Пять обращений к одной и той же виртуальной таблице с разными субконто
ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ_Данные1 ИЗ РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(..., &ВидыСубконто1, ...);
ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ_Данные2 ИЗ РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(..., &ВидыСубконто2, ...);

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

Шаг 1: Подготовка фильтров и отказ от иерархии

Использование конструкции В ИЕРАРХИИ внутри параметров виртуальной таблицы, особенно если там используется подзапрос, — это «смерть» производительности. SQL-серверу крайне тяжело оптимизировать такой план запроса.

Решение: Подготовим плоский список всех нужных счетов (включая все субсчета) заранее во временную таблицу и обязательно её проиндексируем.


ВЫБРАТЬ
    Хозрасчетный.Ссылка КАК Счет
ПОМЕСТИТЬ ВТ_ВсеСчета
ИЗ
    ПланСчетов.Хозрасчетный КАК Хозрасчетный
ГДЕ
    Хозрасчетный.Ссылка В ИЕРАРХИИ (&СписокКорневыхСчетов)
ИНДЕКСИРОВАТЬ ПО
    Счет
;

Теперь в основном запросе вместо В ИЕРАРХИИ мы будем использовать простое условие В (ВЫБРАТЬ Счет ИЗ ВТ_ВсеСчета). Это позволит оптимизатору SQL применить эффективное соединение таблиц.

Шаг 2: Работа с временными таблицами и индексация

Проанализируем работу с временными таблицами (ВТ). Часто программисты забывают, что ВТ без индексов на больших объемах данных работают медленно. Если вы создали ВТ НашиСчета и используете её в нескольких соединениях, добавьте ИНДЕКСИРОВАТЬ ПО.

Также важно сократить количество обращений к виртуальным таблицам регистра бухгалтерии. Рассмотрим стратегию: 1. Получаем максимально широкий набор данных в одну временную таблицу ВТ_ОбщиеОбороты без указания конкретных видов субконто (если это возможно) или с максимальным их набором. 2. Далее работаем уже с этой временной таблицей, фильтруя её и группируя по нужным разрезам.

Шаг 3: Переход к физическим таблицам (продвинутый уровень)

Если виртуальная таблица ОборотыДтКт продолжает работать медленно, вспомним старую мудрость: виртуальные таблицы удобны, но не всегда быстры. В сложных случаях, когда нужно выжать максимум скорости, проанализируем возможность обращения к физической таблице движений РегистрБухгалтерии.Хозрасчетный.

При использовании физической таблицы мы сами управляем соединениями с таблицами субконто. Это избавляет от лишних LEFT JOIN, которые платформа 1С щедро добавляет при использовании ВЫРАЗИТЬ(Субконто КАК ...). Однако помните, что такой запрос будет гораздо сложнее в написании, так как вам придется самостоятельно обрабатывать порядок субконто и знаки оборотов.

Шаг 4: Использование функции ВЫРАЗИТЬ и типизация

При получении субконто из виртуальных таблиц они имеют составной тип. Посмотрим, как это влияет на запрос. Каждое ВЫРАЗИТЬ для поля Субконто заставляет SQL-сервер присоединять таблицу соответствующего справочника. Если у вас 3 субконто и вы используете ВЫРАЗИТЬ для каждого, это +3 соединения к каждой выборке.

Проанализируем ситуацию: если вам не нужны поля из самих справочников (наименование, реквизиты) прямо в этом запросе, возможно, стоит получить просто ссылки, а типизировать их уже при выводе или в самом конце пакета запросов.

Технические нюансы фоновых заданий

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

Итоговые рекомендации для стабильной работы:

  1. Сократите время выполнения. Если запрос будет работать 1-2 минуты вместо часа, вероятность попадания на момент изменения данных снизится почти до нуля.
  2. Индексируйте всё. Каждая временная таблица, которая участвует в соединениях, должна иметь индекс по полям связи.
  3. Проверьте базу на наличие битых ссылок. Иногда «плавающие» данные — признак того, что в измерениях регистра (например, Подразделение) встречаются NULL или битые значения, которые по-разному обрабатываются при построении виртуальных таблиц. Проведите тестирование и исправление базы.
  4. Включите RCSI. Если вы используете MS SQL Server, включение режима Read Committed Snapshot Isolation поможет отчету видеть согласованный «снимок» данных на момент начала запроса, не блокируясь при этом пишущими пользователями.

Следуя этим шагам, мы не только избавимся от «магии» с меняющимися цифрами, но и значительно повысим комфорт работы пользователей, превратив тяжелый часовой отчет в быстрый и точный инструмент аналитики.

← На главную