При написании запросов к периодическим регистрам сведений разработчики часто сталкиваются с вопросом: где правильнее указывать условия — в параметрах виртуальной таблицы (например, СрезПоследних или СрезПервых) или в секции ГДЕ? На первый взгляд может показаться, что при отборе по ключевым полям результат не меняется. Однако в зависимости от того, на какое поле накладывается условие (измерение или ресурс), а также от структуры самого запроса, результат и скорость его выполнения могут кардинально различаться.
Разберем подробно механику работы платформы 1С, выясним причину различий в результатах и проанализируем примеры на практике.
Чтобы понять различия, рассмотрим, как платформа 1С и СУБД обрабатывают условия:
Проанализируем поведение запроса при фильтрации по измерениям регистра (например, по сотруднику, валюте или договору):
ЛЕВОЕ СОЕДИНЕНИЕ поведение меняется. Если отбор по измерению поместить в секцию ГДЕ, условие отсечет строки со значением NULL, неявно превратив соединение во внутреннее. Если же фильтр задан в параметрах виртуальной таблицы, левое соединение сохранит все исходные строки левой таблицы.ГДЕ заставляет СУБД сначала рассчитать срез по всей таблице регистра, что на больших объемах данных приводит к существенному замедлению.Если условие накладывается на ресурс регистра сведений, выборки данных в большинстве случаев будут абсолютно разными. Рассмотрим классический пример с периодическим регистром сведений КурсыВалют, содержащим измерение Валюта и ресурс Курс.
Представим следующие данные в регистре:
Поставим задачу: выбрать валюты на самую раннюю дату, курс которых был меньше 30.
Посмотрим на первый вариант — наложение условия в параметрах виртуальной таблицы:
ВЫБРАТЬ
КурсыВалютСрезПервых.Период КАК Период,
КурсыВалютСрезПервых.Валюта КАК Валюта,
КурсыВалютСрезПервых.Курс КАК Курс
ИЗ
РегистрСведений.КурсыВалют.СрезПервых(, Курс < 30) КАК КурсыВалютСрезПервых
В этом случае платформа сначала отфильтрует физическую таблицу, оставив только запись с курсом 28.30, и затем возьмет срез первых по отфильтрованным строкам. Результатом будет одна строка: Доллар, 01.02.2024, 28.30.
Теперь рассмотрим второй вариант — перенос условия в секцию ГДЕ:
ВЫБРАТЬ
КурсыВалютСрезПервых.Период КАК Период,
КурсыВалютСрезПервых.Валюта КАК Валюта,
КурсыВалютСрезПервых.Курс КАК Курс
ИЗ
РегистрСведений.КурсыВалют.СрезПервых КАК КурсыВалютСрезПервых
ГДЕ
КурсыВалютСрезПервых.Курс < 30
В этом сценарии платформа сначала построит срез первых по всему регистру (получит записи от 01.01.2024: Доллар с курсом 30.25 и Евро с курсом 40.50), а затем применит фильтр Курс < 30. Ни одна из записей среза не удовлетворяет условию, поэтому результат запроса будет пустым.
Проанализируем ситуацию с регистром окладов сотрудников:
ГДЕ Оклад > 50000 — запрос вернет сотрудников, у которых текущий актуальный оклад превышает 50 000. Сотрудники, у которых оклад когда-то был выше, но сейчас снизился, в выборку не попадут.СрезПоследних(, Оклад > 50000) — запрос найдет последнюю запись для каждого сотрудника, когда его оклад превышал 50 000, даже если сейчас его ставка меньше или он вовсе переведен на другую должность.Измерение В (ВЫБРАТЬ Поле ИЗ ВТ_Критерии).ГДЕ. Если требуется «наиболее свежая запись среди тех, которые соответствовали критерию», условие накладывается в параметрах виртуальной таблицы.