vk fb tw rss

Пример оптимизации запроса

Ускорение запроса

Давайте рассмотрим пример оптимизации медленного запроса с одного из реальных проектов по ускорению 1С.

В системе был найден запрос, который работает более 5 секунд, текст запроса приведен ниже:

 

ВЫБРАТЬ

ДенежныеСредстваКПоступлениюБезналичныеОбороты.Документ.Контрагент.Партнер,

МЕСЯЦ(ДенежныеСредстваКПоступлениюБезналичныеОбороты.Период) КАК Месяц,

ГОД(ДенежныеСредстваКПоступлениюБезналичныеОбороты.Период) КАК Год,

СУММА(ДенежныеСредстваКПоступлениюБезналичныеОбороты.СуммаПриход) КАК СуммаПриход

ИЗ

РегистрНакопления.ДенежныеСредстваКПоступлениюБезналичные.Обороты(, , Месяц, Документ.Контрагент.Партнер = &Партнер) КАК ДенежныеСредстваКПоступлениюБезналичныеОбороты

 

СГРУППИРОВАТЬ ПО

ДенежныеСредстваКПоступлениюБезналичныеОбороты.Документ.Контрагент.Партнер,

МЕСЯЦ(ДенежныеСредстваКПоступлениюБезналичныеОбороты.Период),

ГОД(ДенежныеСредстваКПоступлениюБезналичныеОбороты.Период)

 

Наверняка опытный глаз сразу найдет неоптимальное место. В данном случае проблемным местом здесь является обращение через две точки при фильтрации в параметрах виртуальной таблицы.

Казалось бы ничего страшного в этом нет, да вот только поле «Документ» является реквизитом составного типа.

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

Подробнее о проблемах при работе с составными типами можно почитать здесь.

 

Обычно в таких случаях рекомендуется использовать конструкцию «ВЫРАЗИТЬ» и привести поле к определенному типу, что бы избавится от соединения с лишними таблицами. Но мы не можем так поступить по нескольким причинам:

Причина 1. В нашем случае нам необходимы все документы, которые содержит составной тип. Другими словами постановка задачи не позволяет нам ограничиться каким-то одним типом, нужно фильтровать обязательно все типы документов, которые входят в составной тип.

Причина 2. Даже если бы причины 1 не было, то все равно у нас остается обращение через 2 точки к полю, что тоже не очень хорошо.

Причина 3. Даже если бы мы могли использовать «ВЫРАЗИТЬ», то это бы не сильно помогло. Использование «ВЫРАЗИТЬ» в параметрах  виртуальной таблицы не оказывает практически никакого положительного эффекта на производительность.

 

Оптимизация

Итак, после анализа приходим к выводу что нужно избавится от обращений через 2 точки к реквизиту составного типа, но при этом необходимо сохранить логику работы запроса.

Как всегда есть несколько вариантов решения данной задачи, рассмотрим два решения.

 

Решение 1.

Можно добавить в регистр «ДенежныеСредстваКПоступлениюБезналичные» новое измерение «Партнер», и при записи движений заполнять данное поле. Т.к. мы используем условие по этому полю, то рекомендуется его проиндексировать.

В результате мы можем легко наложить фильтр на новоиспеченное поле в параметрах виртуальной таблицы:

 

РегистрНакопления.ДенежныеСредстваКПоступлениюБезналичные.Обороты(, , Месяц, Партнер = &Партнер) КАК ДенежныеСредстваКПоступлениюБезналичныеОбороты

 

Этот запрос будет работать практически моментально.

Плюс у данного способа всего один, это его простота, зато минусов гораздо больше.

Основной минус это изменение текущей структуры конфигурации, как следствие имеем дополнительные проблемы при обновлении, обменах и т.д. Помимо прочего мы храним дублирующуюся информацию, что увеличивает размер таблицы, а новый индекс хоть и увеличивает скорость чтения, но замедляет запись в этот регистр.

К счастью это решение не единственное, давайте рассмотрим второй вариант.

 

Решение 2.

Если немного подумать, то можно переписать запрос таким образом, что бы фильтр накладывался по полю «Документ», например так

 

РегистрНакопления.ДенежныеСредстваКПоступлениюБезналичные.Обороты(, , Месяц, Документ В (ВЫБРАТЬ Ссылка ИЗ ВТ_ДокументыСПартнером)) КАК ДенежныеСредстваКПоступлениюБезналичныеОбороты

 

Давайте подробно рассмотрим метаморфозы запроса, прежде чем он пришел к такому виду.

Во первых нам нужно собрать все документы которые входят в составной тип поля «Документы» , и у этих документов должно выполнятся условие «Контрагент.Партнер = & Партнер»

В составной тип входит 5 документов, но реквизит «Контрагент» есть только у 4х из них, это документы: ОперацияПоПлатежнойКарте, ПоступлениеБезналичныхДенежныхСредств, РасходныйКассовыйОрдер, СписаниеБезналичныхДенежныхСредств

Создадим временную таблицу для фильтрации, с документами у которых поле «Партнер» равно требуемому значению и потом просто применим фильтр по документам в основном запросе.

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ ОперацияПоПлатежнойКарте.Ссылка

ПОМЕСТИТЬ ВТ_ДокументыСПартнером

ИЗ Документ.ОперацияПоПлатежнойКарте КАК ОперацияПоПлатежнойКарте

ГДЕ ОперацияПоПлатежнойКарте.Контрагент.Партнер = &Партнер

 

ОБЪЕДИНИТЬ ВСЕ

 

ВЫБРАТЬ ПоступлениеБезналичныхДенежныхСредств.Ссылка

ИЗ Документ.ПоступлениеБезналичныхДенежныхСредств КАК ПоступлениеБезналичныхДенежныхСредств

ГДЕ ПоступлениеБезналичныхДенежныхСредств.Контрагент.Партнер = &Партнер

 

ОБЪЕДИНИТЬ ВСЕ

 

ВЫБРАТЬ РасходныйКассовыйОрдер.Ссылка

ИЗ Документ.РасходныйКассовыйОрдер КАК РасходныйКассовыйОрдер

ГДЕ РасходныйКассовыйОрдер.Контрагент.Партнер = &Партнер

 

ОБЪЕДИНИТЬ ВСЕ

 

ВЫБРАТЬ СписаниеБезналичныхДенежныхСредств.Ссылка

ИЗ Документ.СписаниеБезналичныхДенежныхСредств КАК СписаниеБезналичныхДенежныхСредств

ГДЕ СписаниеБезналичныхДенежныхСредств.Контрагент.Партнер = &Партнер

;

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ

&Партнер,

МЕСЯЦ(ДенежныеСредстваКПоступлениюБезналичныеОбороты.Период) КАК Месяц,

ГОД(ДенежныеСредстваКПоступлениюБезналичныеОбороты.Период) КАК Год,

ДенежныеСредстваКПоступлениюБезналичныеОбороты.СуммаПриход КАК СуммаПриход

ИЗ

РегистрНакопления.ДенежныеСредстваКПоступлениюБезналичные.Обороты(

,, Месяц, Документ В

(ВЫБРАТЬ

ВТ_ДокументыСПартнером.Ссылка

ИЗ

ВТ_ДокументыСПартнером)) КАК ДенежныеСредстваКПоступлениюБезналичныеОбороты

 

Конечно можно было бы сначала получить всех контрагентов с данным партнером и искать документы с фильтром по контрагенту, но никакой драматической разницы в скорости от этого небыло.

После оптимизации запрос стал выполняться менее секунды.

Минус только в том, что запрос стал сложнее.

Плюсы очевидны, отпала необходимость в создании индексов и изменении структуры метаданных.

 

Вывод

Мы рассмотрели пример оптимизации простого запроса, при этом нам удалось избежать добавления новых полей в регистр и/или создания новых индексов.

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



Лучшие материалы по теме

Расскажите своим друзьям
Вам ничего не стоит, а им будет интересно
Подпишитесь на обновления
Ваш e-mail: * Ваше имя: *


Обсудить Вконтакте


Обсудить в Facebook

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *