Сортировка результата запроса 1С 8.3 без потери скорости
Содержание
Чтобы упорядочить запрос в 1С, в конце текста запроса пишут УПОРЯДОЧИТЬ ПО Поле1 УБЫВ, Поле2. Направление по умолчанию — ВОЗР. Если поле ссылочное и нужен «человеческий» порядок по наименованию или дате, добавьте после списка полей АВТОУПОРЯДОЧИВАНИЕ или сортируйте явно по Поле.Наименование.
Частое заблуждение: «раз записи и так приходят по порядку, сортировка не нужна». Без УПОРЯДОЧИТЬ ПО порядок строк в 1С не гарантирован. Сегодня в файловой базе строки идут по коду, завтра на SQL-сервере они придут в порядке, удобном плану запроса. Для производительности важно другое: сортировать по полям, под которые есть индекс, и не сортировать то, что сортировать не нужно.
Всё ниже относится к языку запросов платформы 8.3 и одинаково для БП 3.0, ЗУП 3.1, УТ 11 и любых других конфигураций.
Как упорядочить результат запроса: синтаксис и порядок секций
Предложение УПОРЯДОЧИТЬ ПО стоит в конце пакета одного запроса: после ГДЕ, СГРУППИРОВАТЬ ПО, ИМЕЮЩИЕ и перед ИТОГИ.
ВЫБРАТЬ
Номенклатура.Ссылка КАК Товар,
Номенклатура.Артикул КАК Артикул,
Номенклатура.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
НЕ Номенклатура.ЭтоГруппа
УПОРЯДОЧИТЬ ПО
Наименование,
Артикул УБЫВ
Что здесь происходит:
- 🔹 строки сортируются сначала по наименованию по возрастанию;
- 🔹 при одинаковом наименовании — по артикулу по убыванию;
- 🔹 в списке можно указывать псевдонимы из
ВЫБРАТЬ(Наименование) или полные пути к полям (Номенклатура.Наименование); - 🔹 сортировать можно и по полю, которого нет в списке выборки, если запрос без группировки.
Направление и типы значений
| Тип поля | Как идёт ВОЗР |
|---|---|
| Число | от меньшего к большему |
| Дата | от ранней к поздней |
| Булево | сначала Ложь, потом Истина |
| Строка | по алфавиту, правила сравнения задаёт СУБД |
| Ссылка без автоупорядочивания | по внутреннему представлению ссылки, не по алфавиту |
Строковые коды сортируются как строки. Код "10" окажется раньше кода "2". Если коды справочника хранятся строкой без ведущих нулей, нужный порядок даст только числовое поле или выражение ВЫРАЗИТЬ.
Конструктор запроса
В конструкторе сортировка задаётся на вкладке Порядок. Перетащите поля из левой колонки в правую и выберите направление в колонке «Сортировка». Флажок «Автоупорядочивание» на той же вкладке добавляет в текст ключевое слово АВТОУПОРЯДОЧИВАНИЕ.
Упорядочивание с ИТОГИ и ОБЪЕДИНИТЬ
- 📌 В запросе с
ИТОГИсортировка работает внутри каждой группировки итогов. Строки детальных записей упорядочены внутри своего итога. - 📌 В запросе с
ОБЪЕДИНИТЬилиОБЪЕДИНИТЬ ВСЕсортировку пишут один раз, после последней части. Она относится ко всему объединению, а поля берутся по псевдонимам первой части.
ВЫБРАТЬ Поступление.Дата КАК Дата, Поступление.Ссылка КАК Документ
ИЗ Документ.ПоступлениеТоваровУслуг КАК Поступление
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Реализация.Дата, Реализация.Ссылка
ИЗ Документ.РеализацияТоваровУслуг КАК Реализация
УПОРЯДОЧИТЬ ПО
Дата УБЫВ
АВТОУПОРЯДОЧИВАНИЕ и ИЕРАРХИЯ: как упорядочить запросы по ссылкам
Здесь чаще всего ошибаются те, кто переходит с SQL. Строка УПОРЯДОЧИТЬ ПО Контрагент сортирует не по наименованию контрагента, а по внутреннему значению ссылки. Для пользователя такой порядок выглядит случайным.
Есть три способа получить понятный порядок:
- Явное поле:
УПОРЯДОЧИТЬ ПО Контрагент.Наименование. Порядок точно предсказуем, но платформа добавит соединение с таблицей справочника. - АВТОУПОРЯДОЧИВАНИЕ: ссылочные поля в списке сортировки заменяются полями, по которым объект упорядочивается по умолчанию. Для справочника это обычно основное представление (код или наименование), для документов — дата.
- Сортировка по полю самой таблицы: если в выборке есть
Номенклатура.Наименование, сортируйте по нему, а не поСсылка.Наименование— лишнего разыменования не будет.
ВЫБРАТЬ
Реализация.Ссылка КАК Документ,
Реализация.Контрагент КАК Контрагент,
Реализация.СуммаДокумента КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
УПОРЯДОЧИТЬ ПО
Контрагент,
Документ
АВТОУПОРЯДОЧИВАНИЕ
АВТОУПОРЯДОЧИВАНИЕ удобно в отчётах и обработках «для людей». В служебных запросах, где порядок нужен для алгоритма, лучше писать поля явно: так проще читать текст и предсказывать план.
Сортировка дерева: ИЕРАРХИЯ
Для иерархических справочников и планов счетов есть ключевое слово ИЕРАРХИЯ. Оно выстраивает строки так, чтобы элементы шли сразу после своей группы:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.Наименование КАК Наименование
ИЗ
Справочник.Номенклатура КАК Номенклатура
УПОРЯДОЧИТЬ ПО
Ссылка ИЕРАРХИЯ
ИЕРАРХИЯ применяется только к полю иерархической таблицы. На большом справочнике такая сортировка заметно тяжелее обычной: платформе нужно учитывать родителей на всех уровнях.
Сортировка по составным типам и разыменованным полям
Составной тип — это поле, где может лежать ссылка на разные объекты: Регистратор у регистров, «Документ-основание», реквизит типа «Справочник.Контрагенты, Справочник.ФизическиеЛица».
При сортировке по такому полю значения разных типов не перемешиваются: сначала они группируются по типу, потом упорядочиваются внутри типа. Порядок самих типов задаёт платформа, на него не стоит опираться в алгоритмах.
Главная ловушка: Регистратор.Дата
// Медленно на большой базе
УПОРЯДОЧИТЬ ПО
Продажи.Регистратор.Дата
Регистратор может ссылаться на десятки видов документов. Чтобы взять у него поле Дата, платформа соединит таблицу регистра с таблицей каждого вида документа-регистратора. Для сортировки миллиона строк это лишние соединения на каждый документ конфигурации.
Как сделать лучше:
- ✅ сортируйте по
Периодрегистра: он равен дате регистратора и уже есть в таблице; - ✅ если нужен именно один вид документа, приведите тип:
ВЫРАЗИТЬ(Продажи.Регистратор КАК Документ.РеализацияТоваровУслуг).Дата; - ✅ для порядка «как в учёте» используйте
МоментВременив документах и регистрах, где это поле есть.
Строки неограниченной длины
Поле типа «Строка» с длиной 0 (неограниченная) нельзя использовать в сортировке, группировке и сравнении. Запрос выдаст ошибку. Выход — привести к ограниченной строке:
УПОРЯДОЧИТЬ ПО
ВЫРАЗИТЬ(Номенклатура.Комментарий КАК СТРОКА(150))
Поля типа ХранилищеЗначения не сортируются вовсе.
Индексы и скорость упорядочивания запроса в 1С
Сортировка дешёвая, когда СУБД может читать строки уже в нужном порядке — по индексу. Тогда отдельной операции сортировки в плане нет, а ВЫБРАТЬ ПЕРВЫЕ 10 … УПОРЯДОЧИТЬ ПО отдаёт результат почти мгновенно.
Какие индексы есть всегда
| Объект | Что индексирует платформа без настроек |
|---|---|
| Справочник | ссылку, код и наименование |
| Документ | ссылку, дату вместе со ссылкой, номер |
| Регистр сведений | измерения в порядке их следования в конфигураторе, у периодического — вместе с периодом |
| Регистр накопления | регистратор и период, таблицы итогов — по измерениям |
Отсюда правила:
- 📈
УПОРЯДОЧИТЬ ПО Дата, Ссылкав документах идёт по индексу; - 📈 сортировка по первым измерениям регистра сведений в порядке их объявления быстрее, чем по последним;
- 📉 сортировка по обычному реквизиту без индекса на большой таблице — это полная сортировка всего результата.
Свойство «Индексировать»
В конфигураторе у реквизита справочника или документа есть свойство «Индексировать» с тремя значениями:
- Не индексировать — значение по умолчанию.
- Индексировать — индекс по реквизиту и ссылке.
- Индексировать с доп. упорядочиванием — в индекс добавляются поля стандартного порядка объекта (у справочника — код или наименование, у документа — дата). Это вариант для динамических списков, где пользователь отбирает по реквизиту и видит строки в привычном порядке.
Индекс ускоряет чтение, но замедляет запись. Не индексируйте всё подряд: каждый индекс увеличивает базу и время проведения документов. Включение индекса в типовой конфигурации — это изменение объекта, которое придётся сохранять при каждом обновлении.
Что ломает использование индекса
- ❌ сортировка по выражению:
УПОРЯДОЧИТЬ ПО ГОД(Дата),ПОДСТРОКА(Наименование, 1, 3); - ❌ сортировка по полю через точку из другой таблицы (
Товар.Родитель.Наименование); - ❌ сортировка по полям в порядке, не совпадающем с индексом (
Ссылка, ДатавместоДата, Ссылка).
Большие выборки: когда сортировка тормозит
Признак проблемы простой: запрос без УПОРЯДОЧИТЬ ПО выполняется за 2 секунды, с ним — за 40. Значит, СУБД сортирует сотни тысяч строк, и результат не помещается в память, отведённую под операцию. В MS SQL такая сортировка уходит в tempdb, в PostgreSQL — во временные файлы на диске.
Приёмы, которые реально помогают
- Сортируйте один раз, в конце.
УПОРЯДОЧИТЬ ПОво временной таблице (ПОМЕСТИТЬ) и во вложенном запросе не задаёт порядок итогового результата. Он имеет смысл там только вместе сПЕРВЫЕ N. - Сначала сократите выборку. Отберите и сгруппируйте данные во временную таблицу, а сортируйте уже 500 итоговых строк, а не 500 000 исходных.
- Разыменовывайте после сокращения. Поля вида
Товар.Наименованиеберите в последнем запросе пакета, где строк мало. - Не сортируйте то, что потом пересортируют. В системе компоновки данных порядок вывода задаётся в настройках варианта на вкладке «Сортировка». Порядок из текста запроса отчёт не обязан сохранять.
- Используйте
ПЕРВЫЕ Nс индексированным полем. Задача «последние 20 документов» решается какВЫБРАТЬ ПЕРВЫЕ 20 … УПОРЯДОЧИТЬ ПО Дата УБЫВи читает 20 строк по индексу, а не всю таблицу.
Пакет: сортировка в конце
ВЫБРАТЬ
Продажи.Номенклатура КАК Номенклатура,
СУММА(Продажи.Сумма) КАК Сумма
ПОМЕСТИТЬ ВТ_Продажи
ИЗ
РегистрНакопления.Продажи КАК Продажи
ГДЕ
Продажи.Период МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
Продажи.Номенклатура
;
ВЫБРАТЬ ПЕРВЫЕ 50
ВТ.Номенклатура КАК Номенклатура,
ВТ.Номенклатура.Наименование КАК Наименование,
ВТ.Сумма КАК Сумма
ИЗ
ВТ_Продажи КАК ВТ
УПОРЯДОЧИТЬ ПО
Сумма УБЫВ
Регистр «Продажи» взят для примера: в вашей конфигурации имя регистра и его измерения могут быть другими.
Как найти тяжёлую сортировку
- 🔍 Замер производительности в конфигураторе (
Отладка → Замер производительности) показывает строку кода, на которой выполняется запрос, и долю времени. - 🔍 Технологический журнал с событиями
DBMSSQLилиDBPOSTGRSдаёт текст SQL-запроса и длительность; с включённым сбором планов — и план. - 🔍 План в СУБД: в MS SQL ищите оператор
Sortс большим числом строк и предупреждение о сбросе вtempdb; в PostgreSQL —EXPLAIN (ANALYZE)и строкуSort Method: external merge.
Если в плане видно Sort по миллионам строк перед Top, значит индекса под порядок нет или выражение в УПОРЯДОЧИТЬ ПО мешает его использовать.
Сортировка в разных СУБД: файловая база, MS SQL, PostgreSQL
Платформа переводит запрос 1С в SQL для конкретной СУБД. Логика результата одинакова, но в деталях порядок может различаться.
| Нюанс | Что учесть |
|---|---|
| Строки | правила сравнения задаёт СУБД; порядок пробелов, знаков препинания и спецсимволов может отличаться между файловой базой и сервером |
| NULL | место NULL при сортировке не стоит закладывать в алгоритм; заменяйте явно через ЕСТЬNULL |
| Одинаковые значения | строки с равным ключом сортировки могут прийти в любом порядке, и он может меняться от запуска к запуску |
| Временные файлы | при нехватке памяти MS SQL использует tempdb, PostgreSQL — временные файлы; медленный диск под ними тормозит все тяжёлые сортировки |
| Файловая база | нет отдельного оптимизатора и планов; большие сортировки упираются в диск и память клиента или сервера 1С |
Стабильный порядок при равных значениях
Если в отчёте или выгрузке важно, чтобы строки не «прыгали», добавьте в конец списка уникальное поле:
УПОРЯДОЧИТЬ ПО
Дата,
Ссылка
Без Ссылка два документа с одной датой и временем могут поменяться местами при следующем выполнении. Для постраничной выгрузки это приводит к пропущенным и задвоенным строкам.
NULL в левом соединении
После ЛЕВОЕ СОЕДИНЕНИЕ поля правой таблицы могут быть NULL. Чтобы такие строки шли в конце независимо от СУБД, сортируйте по выражению:
УПОРЯДОЧИТЬ ПО
ВЫБОР
КОГДА Цены.Цена ЕСТЬ NULL ТОГДА 1
ИНАЧЕ 0
КОНЕЦ,
Цены.Цена УБЫВ
Это выражение индекс не использует, поэтому применяйте его на уже сокращённой выборке.
Когда сортировать не в запросе
Иногда упорядочивать запрос вообще не нужно:
- 🧩 Результат дальше идёт в соединение или временную таблицу — порядок там ничего не даёт.
- 🧩 Данных мало и их потом пересортирует код. Для таблицы значений на несколько сотен строк хватит метода
ТаблицаЗначений.Сортировать("Сумма Убыв, Дата"). - 🧩 Отчёт на СКД. Задавайте порядок в настройках варианта, чтобы пользователь мог менять его без правки текста.
- 🧩 Динамический список. Порядок задаёт сам список и пользователь; в тексте запроса списка сортировка обычно лишняя, а для быстрой сортировки по реквизиту ему нужен индекс.
Обратная ситуация: таблицу на 200 000 строк выгружать в память и сортировать в коде не стоит. Это медленнее, чем отдать работу СУБД, и съедает память сервера 1С.
Ошибки при упорядочивании и как их исправить
Ещё две ошибки, которые не дают сообщения, но дают неверный результат:
- ⚠️ Сортировка по строковому коду даёт порядок
1, 10, 11, 2, 3. Если нужен числовой порядок, сортируйте по числовому полю или по коду с ведущими нулями. - ⚠️
ПЕРВЫЕ NбезУПОРЯДОЧИТЬ ПОвозвращает любые N строк. На файловой базе это могут быть первые по коду, на сервере — какие угодно. Для «последних», «самых дорогих» и подобных выборок сортировка обязательна.