Почему зависает Запрос.Выполнить() в 1С при запросе к регистру бухгалтерии и как решить эту проблему

Программист Бухгалтерский учет IT и автоматизация бизнеса
← На главную

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

Анализ проблемной ситуации

Рассмотрим пример запроса к виртуальной таблице регистра бухгалтерии, который может вызывать длительное зависание СУБД:


ВЫБРАТЬ
	ТиповойОстаткиИОбороты.Субконто1 КАК Субконто1,
	СУММА(ТиповойОстаткиИОбороты.СуммаНачальныйОстаток) КАК СуммаНачальныйОстаток,
	СУММА(ТиповойОстаткиИОбороты.СуммаКонечныйОстаток) КАК СуммаКонечныйОстаток,
	СУММА(ТиповойОстаткиИОбороты.СуммаОборотДт) КАК СуммаОборотДт,
	СУММА(ТиповойОстаткиИОбороты.СуммаОборотКт) КАК СуммаОборотКт,
	СУММА(ТиповойОстаткиИОбороты.КоличествоНачальныйОстаток) КАК КоличествоНачальныйОстаток,
	СУММА(ТиповойОстаткиИОбороты.КоличествоКонечныйОстаток) КАК КоличествоКонечныйОстаток,
	СУММА(ТиповойОстаткиИОбороты.КоличествоОборотДт) КАК КоличествоОборотДт,
	СУММА(ТиповойОстаткиИОбороты.КоличествоОборотКт) КАК КоличествоОборотКт
ИЗ
	РегистрБухгалтерии.Типовой.ОстаткиИОбороты(&Н, &К, Авто, , Счет В (&Счет), , Подразделение В (&Подразделение)) КАК ТиповойОстаткиИОбороты
СГРУППИРОВАТЬ ПО
	ТиповойОстаткиИОбороты.Субконто1

На первый взгляд текст запроса синтаксически корректен, однако на практике вызов Запрос.Выполнить() приводит к зависанию по ряду технических причин. Выясним, почему это происходит и как исправить ошибку.

Основные причины длительного выполнения запроса

  1. Рассогласование или отключение итогов регистра бухгалтерии: Если в конкретной базе отключены или не пересчитаны итоги, платформа 1С не может взять агрегированные данные. СУБД начинает рассчитывать остатки и обороты за всю историю базы по таблице движений, что вызывает жесткую нагрузку и зависание.
  2. Отсутствие фильтрации по видам субконто: Обращение к полю Субконто1 без явного указания списка видов субконто в параметрах виртуальной таблицы заставляет платформу выполнять соединение со всеми возможными таблицами справочников, настроенных для данного плана счетов.
  3. Передача иерархических данных через условие В: Если в параметр &Счет или &Подразделение передается группа (родительский элемент), оператор В не выбирает подчиненные элементы и может приводить к неоптимальному плану запроса.
  4. Неоптимальное группирование и агрегация: Использование явной группировки СГРУППИРОВАТЬ ПО совместно с агрегатными функциями СУММА по полям виртуальной таблицы ОстаткиИОбороты часто является избыточным, так как таблица уже отдает сгруппированные данные в соответствии с выбранной периодичностью.

Шаги по локализации и устранению проблемы

1. Пошаговая диагностика параметров

Для определения причин задержки рекомендуется последовательно отключать параметры виртуальной таблицы в коде. Уберите передачу параметров по одному (например, временно исключите отбор по подразделению или счету), чтобы понять, какое именно условие вызывает ложное сканирование таблиц СУБД (Table Scan).

2. Корректировка отборов и вынос условий

В некоторых сценариях платформа формирует некорректный план SQL-запроса при составных условиях внутри скобок параметризации виртуальной таблицы. Перенос сложного условия из параметров виртуальной таблицы в секцию ГДЕ (WHERE) или оптимизация состава параметров внутри скобок ОстаткиИОбороты(...) позволяет СУБД применить верные индексы.

3. Явное указание видов субконто и использование иерархии

Для правильного формирования запроса разберем следующие правила:

  1. Если в отборе используются счета-группы или группы подразделений, вместо оператора В используйте В ИЕРАРХИИ.
  2. Передавайте в 6-й параметр виртуальной таблицы массив конкретных видов субконто (типа ПланВидовХарактеристик.ВидыСубконто...). Это существенно сократит количество внешних соединений в SQL-запросе.
  3. Вместо периодичности Авто задавайте четкий уровень периодичности (например, Период, Месяц или Регистратор), если требуется детализация.

Посмотрим на оптимизированный вариант запроса:


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

4. Администрирование и пересчет итогов

Если запрос подвисает только в конкретной базе данных при аналогичном коде, обязательно выполните обслуживание базы. Перейдите в режиме Конфигуратора в меню Администрирование — Тестирование и исправление, выберите пункт Пересчет итогов и запустите выполнение. После обновления индексов и итогов регистра бухгалтерии вызов Запрос.Выполнить() будет отрабатывать штатно.

← На главную