В практике разработчика 1С рано или поздно наступает момент, когда простые выборки из одного справочника перестают закрывать потребности бизнеса. Мы сталкиваемся с многостраничными текстами запросов, десятками временных таблиц и программной сборкой кода. В этой статье мы разберем, что именно делает запрос «сложным», с какими трудностями можно столкнуться в типовых конфигурациях вроде ЗУП или ERP, и как современные возможности платформы помогают элегантно решать задачи, которые раньше считались невыполнимыми.
Для начинающего разработчика сложным может показаться даже обычное ЛЕВОЕ СОЕДИНЕНИЕ или использование вложенного запроса. Однако, как показывает практика опытных специалистов, настоящая сложность начинается там, где количество соединений заставляет «рябить в глазах», а структура запроса становится нелинейной. Проанализируем основные критерии сложности:
Рассмотрим забавный, но показательный пример запроса, который часто ставит в тупик даже тех, кто привык к сложным джойнам. Попробуем проанализировать, что вернет следующий код:
ВЫБРАТЬ
СУММА(1)
ИЗ Справочник.Номенклатура
Несмотря на отсутствие соединений, этот запрос требует понимания работы агрегатных функций: он вернет общее количество записей в таблице номенклатуры. Это напоминает нам о том, что сложность не всегда заключается в количестве строк кода, но и в логике обработки данных.
Существует мнение, что ПРАВОЕ СОЕДИНЕНИЕ — это признак «ручной работы» и особой любви к SQL. На самом деле, большинство разработчиков 1С стараются избегать его, так как ЛЕВОЕ СОЕДИНЕНИЕ визуально понятнее: мы берем основную таблицу и дополняем ее данными. Интересно, что в последних версиях платформы Конструктор запроса иногда сам может генерировать правые соединения при изменении порядка таблиц, что порой удивляет даже опытных специалистов. Мы рекомендуем всегда приводить соединения к левому типу для обеспечения читаемости кода другими участниками команды.
Когда мы сталкиваемся с запросом, в котором количество временных таблиц исчисляется десятками или сотнями, основной проблемой становится производительность и нагрузка на TempDB. Рассмотрим шаги по оптимизации таких «монстров»:
Во-первых, проанализируем индексацию. Если временная таблица используется в последующих соединениях, она ОБЯЗАТЕЛЬНО должна быть проиндексирована по полям связи. Без этого СУБД выберет неоптимальный план, и время выполнения вырастет по экспоненте.
// Пример правильного создания временной таблицы с индексом
ВЫБРАТЬ
Номенклатура,
Склад,
КоличествоОстаток
ПОМЕСТИТЬ ВТ_Остатки
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, )
ИНДЕКСИРОВАТЬ ПО
Номенклатура,
Склад
;
Во-вторых, оценим целесообразность дробления. Если пакет слишком велик, имеет смысл выгрузить промежуточный результат в менеджер временных таблиц и выполнить расчет в несколько этапов, делая паузы для очистки ненужных данных. Это особенно актуально для механизмов расчета себестоимости.
Долгое время разработчики 1С жаловались на отсутствие функций, привычных по «чистому» SQL (например, в MS SQL Server или PostgreSQL). Однако платформа 8.3.20 и выше принесла долгожданные изменения. Разберем их подробнее:
ROW_NUMBER(), RANK(), LAG() и LEAD().Посмотрим на пример использования оконной функции для нумерации строк внутри групп, что раньше требовало сложного соединения таблицы самой с собой:
ВЫБРАТЬ
Продажи.Номенклатура,
Продажи.Период,
Продажи.Сумма,
ПОРЯДКОВЫЙ_НОМЕР() OVER (ПАРТИЦИЯ ПО Продажи.Номенклатура УПОРЯДОЧИТЬ ПО Продажи.Период) КАК НомерСтрокиВГруппе
ИЗ
РегистрНакопления.ВыручкаИПродажи КАК Продажи
Этот механизм позволяет значительно упростить текст запроса, делая его короче и быстрее. Раньше для решения такой задачи приходилось использовать соединение по условию Т1.Период >= Т2.Период, что создавало колоссальную нагрузку на сервер при больших объемах данных.
Как же разбираться в чужих сложных запросах? Рассмотрим проверенный инструментарий:
SDBL или DBMSSQL. Это позволит увидеть реальный SQL-текст, который платформа отправила на сервер БД.Index Scan вместо Index Seek на огромной таблице — это верный признак того, что в запросе не хватает индексов или условия в ГДЕ написаны некорректно (например, используется функция над полем индекса).Важный момент: Сложные запросы в типовых шаблонах RLS (ограничение доступа на уровне записей) — это отдельный вид искусства. Для их «вкуривания» рекомендуется использовать производительный режим RLS, который платформа предлагает в последних редакциях. Он заменяет динамическое добавление подзапросов на использование предварительно рассчитанных таблиц прав, что делает итоговый SQL-код гораздо прозрачнее.
Подводя итог, можно сказать, что сложные запросы — это неотъемлемая часть жизни 1С-программиста в сегменте Middle и Senior. Главное — не бояться их объема, активно использовать временные таблицы с индексами и осваивать новые возможности платформы, такие как оконные функции, которые позволяют превратить «простыню» кода в элегантное и быстрое решение.