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