Что быстрее и правильнее использовать в запросах 1С: РАЗЛИЧНЫЕ или СГРУППИРОВАТЬ ПО?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При написании запросов в системе «1С:Предприятие» разработчики часто сталкиваются с задачей исключения дублирующихся строк из результата выборки. Для этого платформа предоставляет два основных инструмента: использование ключевого слова РАЗЛИЧНЫЕ (аналог DISTINCT в SQL) и секцию СГРУППИРОВАТЬ ПО (аналог GROUP BY). На первый взгляд они кажутся взаимозаменяемыми, но так ли это на самом деле? В этой статье мы подробно разберем, какой вариант работает быстрее, проанализируем результаты практических замеров и выясним, в каких ситуациях следует отдавать предпочтение конкретному методу.

Анализ производительности: данные практических замеров

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


ВЫБРАТЬ
    ПартииТоваровОрганизаций.Регистратор КАК Ссылка
ИЗ
    РегистрНакопления.ПартииТоваровОрганизаций КАК ПартииТоваровОрганизаций
ГДЕ
    // некие условия
УПОРЯДОЧИТЬ ПО
    Ссылка
АВТОУПОРЯДОЧИВАНИЕ

Для выяснения истины были проведены замеры в консоли запросов на реальных данных. Выясним, как ведут себя эти операторы при разном объеме записей:

  1. Выборка по справочнику (400 000 записей): При сравнении РАЗЛИЧНЫЕ и СГРУППИРОВАТЬ ПО время выполнения составило около 1 секунды для обоих вариантов. Разница оказалась практически неощутимой.
  2. Выборка по регистру сведений (10 000 000 записей): На таком объеме время выполнения колебалось в районе 5–6 секунд. При этом результаты тестов показывали переменную эффективность: в одном запуске быстрее отрабатывал РАЗЛИЧНЫЕ, в другом — СГРУППИРОВАТЬ ПО.

Проанализировав эти данные, мы можем сделать вывод, что с точки зрения "чистой" скорости выполнения на современных СУБД разница между этими операторами находится в пределах погрешности. Это происходит потому, что оптимизаторы SQL-серверов (MS SQL Server, PostgreSQL) зачастую трансформируют DISTINCT в GROUP BY еще на этапе подготовки плана запроса.

Механизмы выполнения на уровне СУБД

Чтобы понять, почему производительность идентична, разберем внутренние механизмы работы СУБД. Существует два основных способа, которыми сервер баз данных устраняет дубликаты:

Stream Aggregate: Этот метод используется, если данные уже отсортированы (например, выборка идет по индексированному полю). СУБД просто проходит по списку и пропускает повторяющиеся значения. Это самый эффективный сценарий для обоих операторов.

Hash Match: Если данные не отсортированы, СУБД строит в оперативной памяти временную хэш-таблицу, куда помещает уникальные ключи. При обработке каждой новой строки проверяется ее наличие в хэш-таблице. В этом случае и РАЗЛИЧНЫЕ, и СГРУППИРОВАТЬ ПО потребляют одинаковое количество ресурсов процессора и памяти.

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

Несмотря на схожесть в производительности, существуют критические различия в синтаксисе и возможностях работы с данными. Рассмотрим их подробнее:

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


ВЫБРАТЬ
    Номенклатура.Ссылка,
    МАКСИМУМ(Номенклатура.НаименованиеПолное) КАК Описание
ИЗ
    Справочник.Номенклатура КАК Номенклатура
СГРУППИРОВАТЬ ПО
    Номенклатура.Ссылка

Оператор РАЗЛИЧНЫЕ не позволяет применять такие трансформации данных "на лету" в рамках одного уровня запроса.

Влияние на упорядочивание (ORDER BY)

Проанализируем правила сортировки. При использовании РАЗЛИЧНЫЕ стандарт требует, чтобы все поля, указанные в секции УПОРЯДОЧИТЬ ПО, обязательно присутствовали в списке ВЫБРАТЬ. Если вы попытаетесь отсортировать результат по полю, которое не выбрано, запрос вернет ошибку. В случае с СГРУППИРОВАТЬ ПО правила работы с выражениями в сортировке могут быть более гибкими в зависимости от версии платформы и настроек СУБД.

Логические ловушки: ОБЪЕДИНИТЬ ВСЕ

Рассмотрим важный нюанс, упомянутый опытными разработчиками. Существует риск получить неожиданный результат при использовании сложных запросов с объединениями. Если в запросе присутствует инструкция ОБЪЕДИНИТЬ ВСЕ, использование РАЗЛИЧНЫЕ может привести к появлению дублей, если логика объединения была сложной и РАЗЛИЧНЫЕ применилось не к итоговому результату, а к одной из частей. В таких случаях группировка итоговой таблицы во временной таблице или во внешнем запросе является более надежным и предсказуемым решением.

Читаемость и «Семантическая чистота» кода

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

Подведение итогов

Проанализировав ситуацию, мы можем дать следующие рекомендации:

  1. Если ваша цель — только уникальность строк и запрос простой, используйте РАЗЛИЧНЫЕ. Это повышает читаемость кода и сразу заявляет о намерениях разработчика.
  2. Если в запросе требуется использование агрегатных функций (минимум, максимум, сумма) или работа с типами данных, требующими особого обращения, используйте СГРУППИРОВАТЬ ПО.
  3. Не стоит пытаться "оптимизировать" запрос, меняя одно на другое ради скорости. Как показали замеры на 10 миллионах записей, разница в быстродействии отсутствует. Намного важнее следить за индексами и корректностью условий в секции ГДЕ.
  4. Помните о специфике старых версий платформы и динамических списков, где СГРУППИРОВАТЬ ПО могло не поддерживаться в определенных контекстах, хотя в современных конфигурациях на базе 8.3 это ограничение практически нивелировано.

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

← На главную