/1c-query-opt — Оптимизация запросов 1С
Продвинутые паттерны оптимизации запросов за пределами базовых правил.
Когда использовать
-
Сложная многошаговая обработка данных
-
Оптимизация JOIN и подзапросов
-
Работа с отчётами СКД
-
Обработка больших объёмов данных
Временные таблицы
JOIN vs Подзапрос
// ПРАВИЛЬНО: JOIN (обычно быстрее) "ВЫБРАТЬ | Заказы.Ссылка, Контрагенты.ИНН |ИЗ Документ.ЗаказКлиента КАК Заказы | ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты | ПО Заказы.Контрагент = Контрагенты.Ссылка"
// ПЛОХО: Подзапрос в SELECT (N+1) "ВЫБРАТЬ | Заказы.Ссылка, | (ВЫБРАТЬ К.ИНН ИЗ Справочник.Контрагенты КАК К | ГДЕ К.Ссылка = Заказы.Контрагент) КАК ИНН |ИЗ Документ.ЗаказКлиента КАК Заказы"
Никогда не JOIN с подзапросами — используй временные таблицы
// ПЛОХО: JOIN с подзапросом "... ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ... СГРУППИРОВАТЬ ПО ...) КАК Итоги ..."
// ПРАВИЛЬНО: Временная таблица + JOIN "ВЫБРАТЬ ... ПОМЕСТИТЬ ВТИтоги ... ИНДЕКСИРОВАТЬ ПО ...; ВЫБРАТЬ ... ИЗ ... ЛЕВОЕ СОЕДИНЕНИЕ ВТИтоги ..."
Параметры виртуальных таблиц
// ПРАВИЛЬНО: Фильтр В ПАРАМЕТРАХ виртуальной таблицы "ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки( | &Дата, Номенклатура В (&Список)) КАК Остатки"
// ПЛОХО: Виртуальная таблица + ГДЕ "ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата) КАК Остатки |ГДЕ Остатки.Номенклатура В (&Список)"
Составные типы — ВЫРАЗИТЬ
// ПЛОХО: Разыменование составного типа (запрос по ВСЕМ типам) "ВЫБРАТЬ ТоварыНаСкладах.Регистратор.Дата"
// ПРАВИЛЬНО: ВЫРАЗИТЬ к конкретному типу "ВЫБРАТЬ ВЫРАЗИТЬ(ТоварыНаСкладах.Регистратор | КАК Документ.ПоступлениеТоваровУслуг).Дата"
ПРЕДСТАВЛЕНИЕ для отображения
// ПЛОХО: Доп. JOIN через точку "ВЫБРАТЬ ТоварыНаСкладах.Склад.Наименование"
// ПРАВИЛЬНО: Без доп. JOIN "ВЫБРАТЬ ПРЕДСТАВЛЕНИЕ(ТоварыНаСкладах.Склад) КАК Склад"
ИЛИ в ГДЕ → ОБЪЕДИНИТЬ ВСЕ
// ПЛОХО: ИЛИ блокирует индексы "ГДЕ Товары.Артикул = &Артикул ИЛИ Товары.Код = &Код"
// ПРАВИЛЬНО: Два запроса с ОБЪЕДИНИТЬ ВСЕ "ВЫБРАТЬ ... ГДЕ Товары.Артикул = &Артикул |ОБЪЕДИНИТЬ ВСЕ |ВЫБРАТЬ ... ГДЕ Товары.Код = &Код"
ОБЪЕДИНИТЬ vs ОБЪЕДИНИТЬ ВСЕ
Всегда ОБЪЕДИНИТЬ ВСЕ если не нужно удалять дубликаты (быстрее — нет группировки).
Виртуальные таблицы — сначала во временную
// ПРАВИЛЬНО: Сначала извлечь, потом JOIN "ВЫБРАТЬ ... ПОМЕСТИТЬ ВТОстатки |ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата,) ИНДЕКСИРОВАТЬ ПО Номенклатура; |ВЫБРАТЬ ... ИЗ Справочник.Номенклатура ЛЕВОЕ СОЕДИНЕНИЕ ВТОстатки ..."
Индексы
-
Индекс должен содержать все поля условия
-
Поля должны быть в начале индекса
-
Поля должны быть последовательными (без пропусков)
-
ИНДЕКСИРОВАТЬ ПО для временных таблиц при JOIN
Справка: Стандарты ITS по оптимизации запросов