Имя: Пароль:
1C
 
Какое условие соединения быстрее
0 Прохожий
 
19.10.25
15:21
По замерам вроде не особо разница
1 Прохожий
 
19.10.25
15:22
|    РегистрНакопления.Продажи.Обороты(
    |            ,
    |            ,
    |            Регистратор,
    |            ДокументПродажи В
    |                (ВЫБРАТЬ
    |                    Реализации.Реализация
    |                ИЗ
    |                    ВТ_Реализации КАК Реализации)) КАК ПродажиОбороты
    |        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Реализации КАК Реализации
    |        ПО (ВЫБОР
    |                КОГДА ПродажиОбороты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
    |                    ТОГДА Реализации.Реализация = (ВЫРАЗИТЬ(ПродажиОбороты.Регистратор КАК Документ.РеализацияТоваровУслуг))
    |                ИНАЧЕ ЛОЖЬ
    |            КОНЕЦ)
    |        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Реализации КАК Возврат
    |        ПО (ВЫБОР
    |                КОГДА ПродажиОбороты.Регистратор ССЫЛКА Документ.ВозвратТоваровОтПокупателя
    |                    ТОГДА Возврат.Реализация = (ВЫРАЗИТЬ(ВЫРАЗИТЬ(ПродажиОбороты.Регистратор КАК Документ.ВозвратТоваровОтПокупателя).ДокументОснование КАК Документ.РеализацияТоваровУслуг))
    |                ИНАЧЕ ЛОЖЬ
    |            КОНЕЦ)
2 Прохожий
 
19.10.25
15:22
|    РегистрНакопления.Продажи.Обороты(
    |            ,
    |            ,
    |            Регистратор,
    |            ДокументПродажи В
    |                (ВЫБРАТЬ
    |                    Реализации.Реализация
    |                ИЗ
    |                    ВТ_Реализации КАК Реализации)) КАК ПродажиОбороты
    |        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Реализации КАК Реализации
    |        ПО (Реализации.Реализация = (ВЫРАЗИТЬ(ПродажиОбороты.Регистратор КАК Документ.РеализацияТоваровУслуг)))
    |        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Реализации КАК Возврат
    |        ПО (Возврат.Реализация = (ВЫРАЗИТЬ(ВЫРАЗИТЬ(ПродажиОбороты.Регистратор КАК Документ.ВозвратТоваровОтПокупателя).ДокументОснование КАК Документ.РеализацияТоваровУслуг)))
3 Прохожий
 
19.10.25
15:23
Есть смысл через Выбор проверять регистратор и дальше не лезть?
4 Волшебник
 
19.10.25
15:37
Может сделаете замер производительности?
5 maxab72
 
19.10.25
15:59
(0) Надо смотреть на тот запрос, что сформирует SQL. А это зависит не только от текста самого запроса.
6 Прохожий
 
19.10.25
15:59
Сделал. Разницы практически нет.
7 Прохожий
 
19.10.25
16:01
(5) Тогда выберу второй. Он классичнее. Просто сама идея первого до конца не понятна. Вот возвратов же меньше гораздо. Дешевле проверить на ссылку или соединить с двумя таблицами регистратор?
8 maxab72
 
19.10.25
16:24
(7) вполне возможно, что SQL для этих двух вариантов сгенерил два идентичных конечных запроса к базе. и поэтому, действительно, лучше остановиться на запросе с более прозрачной структурой (самому же потом в него придется когда-нибудь лезть).
9 Wern
 
19.10.25
16:30
Вот это
"(ВЫРАЗИТЬ(ПродажиОбороты.Регистратор КАК Документ.РеализацияТоваровУслуг))"
тоже можно убрать до
"ПродажиОбороты.Регистратор"
и
"ВЫРАЗИТЬ(ВЫРАЗИТЬ(ПродажиОбороты.Регистратор КАК Документ.ВозвратТоваровОтПокупателя).ДокументОснование КАК Документ.РеализацияТоваровУслуг)))"
преврати в
"ВЫРАЗИТЬ(ПродажиОбороты.Регистратор КАК Документ.ВозвратТоваровОтПокупателя).ДокументОснование)"

ВЫРАЗИТЬ надо чтоб исключить обращение к лишним таблицам, а  тут идет обращение только к УИД который записан в самом реквизите никакого обращения к таблицам не идет потому ВЫРАЗИТЬ не нужно оно ничего не делает. А вот при обращении к ".ДокументОснование" ВЫРАЗИТЬ нужно.

Потому и эти условия ВЫБОР тоже почти ничего не делают. Мы обращаемся к тому что лежит в поле Регистратор, тип в этом поле тоже есть, потому в первом запросе будут 2 проверки первая на тип вторая на УИД, во втором только одна на УИД. Теоретически второй случай быстрее, но разница совсем минимальная. Никак лишних соединений тут нет ни в первом, ни во втором случае.
10 Dmitrii
 
гуру
19.10.25
16:44
(1) Зачем такие сложные конструкции?
Замени ВЫБОР на обычное условие.
Вместо

|ПО (ВЫБОР
|     КОГДА ПродажиОбороты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
|       ТОГДА Реализации.Реализация = (ВЫРАЗИТЬ(ПродажиОбороты.Регистратор КАК Документ.РеализацияТоваровУслуг))
|     ИНАЧЕ ЛОЖЬ
|   КОНЕЦ)

написать:

|ПО ПродажиОбороты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
|   И Реализации.Реализация = ПродажиОбороты.Регистратор
11 Прохожий
 
19.10.25
20:38
(9, 10) Да, так интересно
12 Garykom
 
гуру
20.10.25
08:41
1. Зачем использовать подзапросы вместо соединений с временными таблицами?
2. Зачем извращаться с условиями в виртуальных таблицах, когда можно построить нормальный запрос к полным?
И это будет ничуть не тормозней если правильно делать и нет проблем в СКД
13 unenu
 
20.10.25
09:32
от Выбор Когда в тяжелых соединениях необходимо избавляться на стадии первичных пакетов формирования ВТ.
14 Garykom
 
гуру
20.10.25
10:32
(13) Использование Выбор Когда в соединениях ПО это конечно тот еще ахтунг да
Ладно еще в условиях ГДЕ, хотя там тоже нежелательно
15 RomanYS
 
20.10.25
10:56
(12) спорные утверждения.
Простой подзапрос в условиях виртуальной таблицы вполне себе нормальная практика.
16 Garykom
 
гуру
20.10.25
11:10
(15)
Пояснение
Виртуальная таблица - это удобная вещь для обращения к данным регистра. Виртуальная таблица скрывает подробности своей работы, предоставляя понятный способ обращения к данным. В частности, виртуальная таблица по-разному формирует запросы к базе данных в зависимости от того, какой режим работы у регистра (включено ли хранение актуальных итогов, рассчитаны ли итоги и на какой последний период). Она может как использовать временные таблицы базы данных, так и сформировать подзапрос.

Параметр Условие предназначен для того, чтобы сократить объем данных, обрабатываемый при работе виртуальной таблицы. Важно понимать, что при использовании временной таблицы никакой оптимизатор СУБД не сможет распознать, что из временной таблицы в последствии будет использована лишь часть данных, а следовательно без правильного указания параметра Условие заполнение временной таблицы ненужными данными часто может быть причиной проблем с производительностью.

С другой стороны, если в параметр Условие заложить слишком много, то такой подход также может принести больше проблем, нежели пользы.

В процессе разбора одной из проблем производительности в конфигурации был обнаружен запрос к виртуальной таблице регистра, при этом в параметре Условие было указано выражение с подзапросом и соединениями двух табличных частей. Более того, из-за использования неявных соединений (использования выражения через точку в выражении языка запросов) количество таблиц в этом выражении выросло еще больше. Это привело к отрицательному результату - вместо увеличения производительности получилось уменьшение скорости работы.

Рекомендация
При обращении к виртуальной таблице следует передавать в условия наиболее простые конструкции, например, "Измерение = Значение". Не рекомендуется использовать подзапросы и соединения(*) в параметрах виртуальной таблицы, так как это приводит к медленной работе запроса.

https://its.1c.ru/db/metod8dev/content/5457/hdoc
17 Garykom
 
гуру
20.10.25
11:13
(16)+ Если очень надо - можно динамически формировать текст запроса
Или с передачей параметров в т.ч. списков/массивов
18 RomanYS
 
20.10.25
11:22
(16) по твоей же ссылке. Найди отличия с (0)
19 Garykom
 
гуру
20.10.25
11:39
(18) да в данном случае нормально, ибо простое
но плохо читается, если есть возможность можно отдельно выполнить запрос и передать параметром
чтобы было просто
|    РегистрНакопления.Продажи.Обороты(
|            ,
|            ,
|            Регистратор,
|            ДокументПродажи В (&МассивДокументовПродажи)
20 aka MIK
 
20.10.25
12:00
(19) это не обязательно. Если в условиях виртуальной таблицы будет в подзапросе обращение к данным временной таблицы, и там будет ограниченное к-во данных, то сработает нормально. Главное чтобы оптимизатор запроса знал сколько в подзапросе строк еще до начала выполнения запроса
21 Wern
 
20.10.25
13:54
(19) Вот этого как раз не надо. Передавать список документов с SQL сервера на сервер приложений сохранять его там в памяти, передавать его обратно на SQL сервер. Это все сильно не на пользу производительности.
22 scanduta
 
20.10.25
15:23
(0) Конечно через ВЫРАЗИТЬ на больших объемах будет быстрее намного работать. Проверено на практике. На малых объемах без разницы
23 aka MIK
 
20.10.25
16:47
(21) затраты ресурсов на передачу списка для отбора на порядки меньше чем затраты SQL на запрос без корректного отбора
24 Wern
 
20.10.25
17:02
(23) Только вот там корректный отбор.
25 RomanYS
 
20.10.25
17:14
(22) Не "конечно"! В (9) правильно расписано, когда польза от ВЫРАЗИТЬ есть, а когда только вред для читаемости.
26 Dmitrii
 
гуру
20.10.25
17:37
(25) >> В (9) правильно расписано...

Нет. В (9) допущена ошибка в рассуждениях.

Дело в том, что автор ветки использовал выражение ВЫРАЗИТЬ для того, чтобы ограничить условие соединения с конкретными таблицами - Документ.РеализацияТоваровУслуг (для отбора продаж) и Документ.ВозвратТоваровОтПокупателя (для отбора возвратов). Он почему-то отказался от оператора ССЫЛКА в пользу ВЫРАЗИТЬ.
Если убрать эти ВЫРАЗИТЬ, запрос вернёт другие результаты.
ВЫРАЗИТЬ можно убрать, если заменить их на логический оператор ССЫЛКА, как я предложил в (10).
27 RomanYS
 
20.10.25
17:56
(26) ТС использовал ВЫРАЗИТЬ потому что как и (22) где-то слышал звон... и пытался ускорить.
Получался ли у него правильный результат и что он вообще делал, мы не знаем.
Поэтому с "запрос вернёт другие результаты" готов согласиться, но возможно этот результат будет лучше прежнего)))
А в (9) правильная попытка объяснить, когда ВЫРАЗИТЬ может что-то ускорить
28 Garykom
 
гуру
20.10.25
18:05
(27) ВЫРАЗИТЬ для составных ускоряет когда запрос в SQL не транслируется с лишними соединениями
29 Wern
 
20.10.25
18:08
(26) Согласен. В (9) моя ошибка в плане того что если в "ВТ_Реализации" кроме "РеализацияТоваровУслуг" лежат какие то другие документы, то мы получим отличный от (0) результат. Но и с (27) соглашусь, не думаю что ТС намерено использовал "ВЫРАЗИТЬ" для этих целей.
30 Dmitrii
 
гуру
20.10.25
21:55
(27) (29) >> не думаю что ТС намерено использовал "ВЫРАЗИТЬ" для этих целей.

Парни... Если бы я хотел кого-то обидеть, то мне пришлось бы начать с себя. Я точно так же, как и вы, сначала упустил эту логику. И даже начал было писать пост аналогичный (9). Но потом просто задался вопросом - а нафига тут два соединения и чем именно они будут отличаться, если мы уберём ВЫРАЗИТЬ и оставим только в первой связи только условие Реализация=Регистратор? И тут всё стало понятно. Даже если автор тупо использовал ВЫРАЗИТЬ только потому, что "где-то слышал звон... и пытался ускорить", ему удалось одновременно решить вопрос отбора в одной связи по документам продажи, а в другой - по документам возврата.
Так что либо оставляем ВЫРАЗИТЬ, либо заменяем на использование ССЫЛКА. И в любом случае конструкцию следует оставить "(ВЫРАЗИТЬ(ПродажиОбороты.Регистратор КАК Документ.ВозвратТоваровОтПокупателя).ДокументОснование" для удаления лишних неявных левых соединений с таблицами всех возможных регистраторов нашего регистра.
31 H A D G E H O G s
 
20.10.25
22:38
Убирать ВЫРАЗИТЬ из соединений тут не обязательно, никакими индексами в соединениях тут не пахнет.

А вот проиндексировать поле "Реализация" в ВТ "ВТ_Реализации"
нужно.

Это редкий, исчезающе--редкий случай, когда нужна индексация ВТ, причем:
1) Если ВТ будет мала (меньше процента от размера таблицы для MSSQL) - будет использоваться индекс в параметрах виртуальной таблице и СОРТИРОВКА по индексу в соединении с временной таблицей.
2) Если ВТ будет велика - будет использоваться СОРТИРОВКА индекса для соединения слиянием в параметрах виртуальной таблице и тажа СОРТИРОВКА индекса в соединении с временной таблицей.

Если не Индексировать ВТ, для 2-ого варианта 1С 2 раза отсортирует ВременнуюТаблицу.

Короче, индексирование ВТ заменяет Сортировку ВТ, которую не завезли в платформу.
32 Dmitrii
 
гуру
20.10.25
23:08
Ну раз пошла такая пьянка,....

А нафига тут вообще виртуальная таблица Обороты, если периодичность "Регистратор" и нет отбора по периоду?
Если регистр накопления оборотный (что скорее всего), то с высокой долей вероятности, запрос к первичной таблице движений будет работать гораздо быстрее. А в зависимости от того на кой вообще нужен этот запрос, потом можно результат и сгруппировать по нужным полям.

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

PS И это мы ещё на задались вопросом о том как и откуда берётся таблица ВТ_Реализации и зачем вообще всё это нужно (для отчета в СКД, сбор данных для проведения какого-нибудь документа или какое-нибудь заполнение в какой-нибудь обработке).......
33 Wern
 
21.10.25
10:51
(32) Так там же и так будет запрос к первичной таблице, даже с виртуальной таблицей Обороты. Тут главное чтоб "Реализации.Реализация" проиндексировано было. За счет чего первичная таблица будет работать гараздо быстрее чем виртуальная таблица оборотов? Может ты про скрытую группировку в виртуальной таблице, которой нет в основной таблице регистра? Ну врятли ТС нужна не сгруппированная таблица регистра. Или про вложенные запросы? Он тут максимально простой, проблема возникает когда оптимизатор не в состоянии определить количество строк во вложенном запросе до его выполнения. А тут во вложенном запросе одна таблица и никаких соединений и условий, к тому же используемая таблица "ВТ_Реализации" только что была сформирована, статистики свежи как никогда. Никаких шансов что оптимизатор сформирует неоптимальный план запроса.

А раз разницы нет лучше сразу использовать виртуальную таблицу чтоб не пришлось ТС лезть в дебри и думать когда какую таблицу лучше применять.