Есть такой регистр сведений: 3 измерения, один ресурс, два измерения ведущие, на третьем стоит "индексировать".
Это регистр самый часто используемый (100+ пользователей), и периодически запрос к нему формируется крайней медленно, сейчас замерял под одним пользователем 65 вызовов запроса - 46 секунд.
Подскажите, можно ли его как то оптимизировать, в чем может быть проблема?
Вот текст запроса:
Запрос = Новый Запрос("ВЫБРАТЬ
| УстановленныеПараметрыСрезПоследних.Значение КАК Значение
|ИЗ
| РегистрСведений.УстановленныеПараметры.СрезПоследних(&Период, Измерение1= &Измерение1 И Измерение2= &Измерение2 И Измерение3= &Измерение3) КАК УстановленныеПараметрыСрезПоследних");
Запрос.УстановитьПараметр("Период", Период);
Запрос.УстановитьПараметр("Измерение1", Измерение1);
Запрос.УстановитьПараметр("Измерение2", Измерение2);
Запрос.УстановитьПараметр("Измерение3", Измерение3);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Значение = Выборка.Значение;
КонецЕсли;
сейчас замерял под одним пользователем 65 вызовов запроса - 46 секунд.
Расшифруйте подробнее. Это время каждого запроса? Время всех 65 запросов? Это 65 вызовов в течении 46 секунд?
Это чистое время выполнение запроса? Как используется полученное значение?
Может получается ссылка и показывается пользователю, тогда понятно время дополнительного получения представление ссылочного типа и это можно поправить. Нужно больше информации.
Индексы по всем реквизитам это вполне бессмысленная вещь.
Но может тут надо в принципе пересмотреть идеологию. Сократить количество вызовов, или кэшировать как-то, или еще что-то.
Есть ли в измерениях составной тип данных Ссылочный и примитивные типы? Вообще в профайлере надо посмотреть используются ли индексы или нет. Бывает из за составных типов индексы не работают. Такой простой запрос должен выполнятся мгновенно.
(1) Такое длительное время выполнения - всегда составляет примерно одинаковое значение?
Может дело в блокировках - если регистр часто дополняется данными. Тогда время должно быть разным в зависимости от нагрузки.
Во-первых: Включен ли у Вас основной отбор по периоду в регистре? В топике про это ни слова.
Во-вторых:
два измерения ведущие, на третьем стоит "индексировать"
Если индексация только по 3-му измерению, то почему в условиях отбора оно на последнем месте? Имхо, отбор будет быстрее, если наложить его в первую очередь на индексируемое измерение.
В третьих: Если у Вас всегда в запросе используются 3 (три) измерения в качестве условий то включите их в "основной отбор" вместе с периодом. Индексацию при этом можно отключить.
В четвертых: Составные типы данных. Если они есть в измерениях, то лучше заменить их на унарный тип. Например создать справочник с реквизитом составного типа и в нем хранить значения, а в измерении регистра использовать только этот справочник.
(12) А как основной отбор мог повлиять на производительность? Насколько я понял, он используется только при обмене данных при регистрации изменений. https://its.1c.ru/db/intgr83#content:119:1
(13) Есть и альтернативное мнение:)
Отсюда: Про индексы и производительность "Неявным образом индексы создаются с учетом типов полей ключа данных — набора полей, однозначно определяющих данные. Для объектных типов данных (Справочник, Документ, ПланСчетов и др.) — это «Ссылка»; для регистров, подчиненных регистратору (РегистрНакопления, РегистрБухгалтерии, РегистрСведений, подчиненный регистратору и др.) — «Регистратор»; для регистров сведений, неподчиненных регистратору — поля, соответствующие изменениям, входящим в основной отбор регистра; для констант — идентификатор объекта метаданных Константы."
Но если брать сухую теорию, то индекс содержащий Период+Измерения1+Измерени2+... создается всегда и когда запрос использует срез по всем измерениям никакого дополнительного волшебства не нужно, разве что переставить самые вариативные измерения в начало.
При этом галки "Ведущее" и "Индексировать" вообще не ускоряют поиск, так как лишь создают дополнительный индекс с отмеченным измерением/ресурсом впереди, а не на его позиции в порядке следования. Эти индексы ускоряют отбор по индексированному полю, но при отборе сразу по всем всем измерениям эти индексы ни о чем.
Так что, как вариант, можно предположить, что из-за "ведущих" и "индексировать" СУБД путается в лишних индексах и строит не оптимальный план запроса, который использует самый не подходящий индекс. Нужно убрать лишние индексы, добавить новый подходящий и/или переписать запрос, чтобы заставить СУБД "переосмыслить" план.
В регистре и так есть индекс по всем измерениям и периоду., поэтому индексировать Измерение3 нужно только в одном случае - если есть поиск по нему одному. Плюс индекс - дополнительное время записи, на время чтения не влияет.
Вообще, запросы в цикле - это нехорошо. Если в регистре не очень много записей, то сделайте функцию повторного использования, например, которая бы возвращала результат запроса по этим трем измерениям, но лучше запрос делать не на конкретный срез измерений, а на все нужные в данный момент.
Вообще, чтобы ускорить данный процесс (не запрос, а именно процесс), необходимо понять задачу целиком: характер данных в регистре, кейс использования данных, объем данных, целевые показатели по времени и т.д. Все решаемо (пример: список недействительных паспортов загружался в регистр сведений 8 часов, убрали регистр вообще - стал загружаться 8 минут, скорость проверки тоже увеличилась в разы, на с++ вообще за 1,5 сек грузится по данному алгоритму, при том сформированный список из 100кк паспортов проверяется меньше, чем за секунду).