Имя: Пароль:
1C
1С v8
Какой запрос оптимальнее
0 posq
 
06.10.14
11:05
Не могу решить какой запрос оптимальнее подскажите. К сожалению по оптимальности теорию прочитал, а вывод сделать не могу. Тесты в силу определенный причин провести не могу.
Задача: Есть Справочник с табличной частью, необходимо выбрать элемент справочника у которого реквизит в "шапке" удовлетворяет условию и в табличной части есть запись с удовлетворяющая условию.

Оригинал (с моей точки зрения не оптимален):

ВЫБРАТЬ
    ДомаПоДоговору.Дом КАК Дом,
    ДомаПоДоговору.Ссылка КАК Договор,
    ДомаПоДоговору.Ссылка.Сумма КАК Сумма,
    ДомаПоДоговору.Ссылка.ПредметДоговора КАК ПредметДоговора
ИЗ
    Справочник.ДоговорыЖКХ.Дома КАК ДомаПоДоговору
ГДЕ
    ДомаПоДоговору.Дом = &Ссылка
    И ДомаПоДоговору.Ссылка.Владелец = &ЖКХ
//////////////////////////////////////////////////////////////////

Мой вариант 1:
ВЫБРАТЬ
    ДомаПоДоговору.Дом КАК Дом,
    ДоговорыЖКХ.Ссылка,
    ДоговорыЖКХ.Сумма КАК Сумма,
    ДоговорыЖКХ.ПредметДоговора КАК ПредметДоговора,
    ДоговорыЖКХ.НомерДоговора,
    ДоговорыЖКХ.ДатаДоговора
ИЗ
    Справочник.ДоговорыЖКХ.Дома КАК ДомаПоДоговору
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ДоговорыЖКХ КАК ДоговорыЖКХ
        ПО ДомаПоДоговору.Ссылка = ДоговорыЖКХ.Ссылка
ГДЕ
    ДомаПоДоговору.Дом = &Дом
    И ДоговорыЖКХ.Владелец = &ЖКХ
/////////////////////////////////////////////////////////////////////

Мой вариант 2:
ВЫБРАТЬ
    ДоговорыПоЖКХ.Ссылка,
    ДоговорыПоЖКХ.Сумма,
    ДоговорыПоЖКХ.ПредметДоговора,
    ДоговорыПоЖКХ.НомерДоговора,
    ДоговорыПоЖКХ.ДатаДоговора
ИЗ
    (ВЫБРАТЬ
        ДомаПоДоговору.Ссылка КАК Ссылка
    ИЗ
        Справочник.ДоговорыЖКХ.Дома КАК ДомаПоДоговору
    ГДЕ
        ДомаПоДоговору.Дом = &Дом) КАК ДоговорыПоДому
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
            ДоговорыЖКХ.Ссылка КАК Ссылка,
            ДоговорыЖКХ.Сумма КАК Сумма,
            ДоговорыЖКХ.ПредметДоговора КАК ПредметДоговора,
            ДоговорыЖКХ.НомерДоговора КАК НомерДоговора,
            ДоговорыЖКХ.ДатаДоговора КАК ДатаДоговора
        ИЗ
            Справочник.ДоговорыЖКХ КАК ДоговорыЖКХ
        ГДЕ
            ДоговорыЖКХ.Владелец = &ЖКХ) КАК ДоговорыПоЖКХ
        ПО ДоговорыПоДому.Ссылка.Ссылка = ДоговорыПоЖКХ.Ссылка
1 Ёпрст
 
06.10.14
11:07
(0) то что оригинал
2 posq
 
06.10.14
11:07
Будет ли мой "не красивый" первый вариант "оптимальнее" оригинала?

И действительно ли мой второй вариант лучше двух предыдущих?
Есть ли смысл оптимизировать?
3 Maxus43
 
06.10.14
11:08
Оригинал.
Следующие варианты УГ какое-то
4 Maxus43
 
06.10.14
11:09
хотя по условию тут можно ещё логически подумать...
ГДЕ
    ДомаПоДоговору.Дом = &Ссылка
    И ДомаПоДоговору.Ссылка.Владелец = &ЖКХ


разве один Дом может быть у разных ЖКХ? лишнее условие имхо
5 posq
 
06.10.14
11:09
Первый вариант красивее внешне согласен.
Но везде же пишут что обращение через точку это очень плохо?)
6 mergan
 
06.10.14
11:10
не понятно для чего в простых запросах по одной таблице лепить соединения
7 Ёпрст
 
06.10.14
11:10
(2) нет
8 Maxus43
 
06.10.14
11:11
(5) выбор из Вложенного запроса - плохо.

Через точку не плохо, это просто превращается в вариант с соединением, и это надо помнить. К составному типу через точку - вот засада
9 posq
 
06.10.14
11:12
Я всю жизнь писал так как в первом варианте, но во всех мануалах по оптимизации пишут что обращение через точку - ужасно)
10 hhhh
 
06.10.14
11:12
(5) во втором варианте система всё равно делает через точку. ТОлько без вашего ведома. Что еще хуже.
11 Maxus43
 
06.10.14
11:13
ПО ДоговорыПоДому.Ссылка.Ссылка = ДоговорыПоЖКХ.Ссылка

забыл ты дописать ещё .Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка.Ссылка
12 DirecTwiX
 
06.10.14
11:13
(5) Там за точкой только одна таблица скрывается - будет только одно соединение, а не несколько. Это нормально.
13 hhhh
 
06.10.14
11:13
(10)+ нет, наоборот, в первом варианте система вместо точки подставляет соединение.
14 Лодырь
 
06.10.14
11:14
(9) Обращение ужасно, если  у тебя идет неявное соединение с несколькими таблицами при составном типе. А так - ничего ужасного не произойдет.
15 posq
 
06.10.14
11:15
(8) Про составные типы ясно.
Но у Чистова на сайте и не только у него слышал что если пишем обращение через точку СУБД его превратит в соединение и что если пишем, то лучше самим написать обращение к таблице.
(11) Это просто описка.
16 боксер
 
06.10.14
11:17
(0)а проверить, если так паришься проблема?
сделай цикл тыщу раз вызови разные варианты и время замерь. сравни.
чем больше тестов тем корректнее сравнение
17 Maxus43
 
06.10.14
11:19
(15) в данном случае не соглашусь, в таких простых примерах монопесуально как напишешь
18 posq
 
06.10.14
11:19
Просто теории начитался(в т.ч. и от сюда http://kb.1c.ru/articleView.jsp?id=44) теперь пытаюсь применять, но столько доп. вопросов возникать начинает, что можно так или иначе переписать запрос.
19 posq
 
06.10.14
11:20
(17) Ясно.
20 Maxus43
 
06.10.14
11:22
(18) Не усложняй без необходимости, тут главное ключевые места правильно писать, типа как с составными
21 posq
 
06.10.14
11:27
Еще вопрос ускоряет ли выборку описание условий к виртуальной таблице через "выбор когда.." или можно все написать через "И".
Например вот так:
ВЫБРАТЬ
    ВЫРАЗИТЬ(СостоянияДокументовСрезПоследних.Документ КАК Документ.ЗапросНаОбслуживание) КАК Документ,
    МАКСИМУМ(СостоянияДокументовСрезПоследних.Период) КАК Период
ПОМЕСТИТЬ ОтобранныеДокументыДокументы
ИЗ
    РегистрСведений.СостоянияДокументов.СрезПоследних(
            &ТекущаяДата,
            ВЫБОР
                КОГДА Документ ССЫЛКА Документ.ЗапросНаОбслуживание
                    ТОГДА ВЫБОР
                            КОГДА НЕ ВЫРАЗИТЬ(Документ КАК Документ.ЗапросНаОбслуживание).Состояние = ЗНАЧЕНИЕ(Справочник.СостоянияДокументов.Закрыт)
                                ТОГДА ВЫБОР
                                        КОГДА РАЗНОСТЬДАТ(Период, &ТекущаяДата, ЧАС) > &ЛимитВремени
                                            ТОГДА ВЫБОР
                                                    КОГДА ВЫРАЗИТЬ(Документ КАК Документ.ЗапросНаОбслуживание).ВидЗапроса = ЗНАЧЕНИЕ(Перечисление.ВидыЗапросовНаОблсуживание.УстранениеСбоя)
                                                        ТОГДА ВЫБОР
                                                                КОГДА ВЫРАЗИТЬ(Документ КАК Документ.ЗапросНаОбслуживание).Клиент.ЮрФизЛицо = ЗНАЧЕНИЕ(Перечисление.ТипыКлиентов.ЮридическоеЛицо)
                                                                    ТОГДА ВЫБОР
                                                                            КОГДА ВЫРАЗИТЬ(Документ КАК Документ.ЗапросНаОбслуживание).Клиент.Приоритет В (&МассивПриоритетов)
                                                                                ТОГДА ИСТИНА
                                                                            ИНАЧЕ ЛОЖЬ
                                                                        КОНЕЦ
                                                                ИНАЧЕ ЛОЖЬ
                                                            КОНЕЦ
                                                    ИНАЧЕ ЛОЖЬ
                                                КОНЕЦ
                                        ИНАЧЕ ЛОЖЬ
                                    КОНЕЦ
                            ИНАЧЕ ЛОЖЬ
                        КОНЕЦ
                ИНАЧЕ ЛОЖЬ
            КОНЕЦ) КАК СостоянияДокументовСрезПоследних

СГРУППИРОВАТЬ ПО
    ВЫРАЗИТЬ(СостоянияДокументовСрезПоследних.Документ КАК Документ.ЗапросНаОбслуживание)
;
22 hhhh
 
06.10.14
11:36
(21) наоборот, замедляет
23 Зеленый пень
 
06.10.14
11:37
(21) Мощное условие (так вот почему в ЖКХ так медленно все работают - ждут результатов из БД:) ) !
По теме: подозрение на неправильную структуру регистра, почему не используются данные регистра для условий?
И непонятно, зачем вообще в данном случае регистр, если всё строится по одному виду документа?
А при большом размере БД СрезПоследних() загнется с таким запросом.
24 zak555
 
06.10.14
11:37
(21) xnj 'nj &
25 zak555
 
06.10.14
11:37
*что это ?
26 DirecTwiX
 
06.10.14
11:47
(21) Разные случае бывают. Можешь замедлить выборку, если неправильный порядок укажешь.
Но пример какой-то страшный -.-
27 zak555
 
06.10.14
11:48
(21) не проще это переписать ?
28 qwerty
 
06.10.14
11:53
Можно попробовать сначала выбрать все договора по владельцу во временную таблицу. Но не думаю что это будет оптимальнее, чем оригинал.
29 qwerty
 
06.10.14
11:55
А вообще, профайлер в руки. Попробуй все варианты, вибери оптимальный, сделай выводы.
30 posq
 
06.10.14
12:18
(22) Т.е. лучше через "И"?
(23) Необходимо поле "период" из регистра, но не в этом дело. Вопрос в том ускоряет или наоборот и почему. Объем записей в регистре приличный.
(27) Переписать через "И"?
(28) Попробую, но сейчас вопрос именно в теории.

Смысл вопроса как раз в том в любых запросах ускоряет ли такое написание или нет.
Я самым последним поместил, по моему мнению, самое тяжелое сравнение. Есть ли смысл?
31 DirecTwiX
 
06.10.14
12:21
(30) В любых не ускоряет. В некоторых - ускоряет.
Самое тяжелое писать в конец имеет смысл.
32 zak555
 
06.10.14
12:23
(30) что там трудного ?

тебе нужно отобрать данные из таблицы Документ.ЗапросНаОбслуживание, где Состояние != Закрыт и с ней работать
33 posq
 
06.10.14
12:33
(32) На оборот любой роме закрыт
НЕ ВЫРАЗИТЬ(Документ КАК Документ.ЗапросНаОбслуживание).Состояние = ЗНАЧЕНИЕ(Справочник.СостоянияДокументов.Закрыт)

В документе нигде не хранится время последнего изменения состояния. Дата документа <> "время изменения последнего состояния".
34 Зеленый пень
 
06.10.14
12:33
(30) " ускоряет или наоборот" - по сравнению с чем?
Если играться аналогичными условиями внутри вирт.таблицы, это кардинально ничего не изменит.
Надо понимать, как SQL строит сам СрезПоследних - это очень тяжелый запрос, и он в процессе посторения среза к каждой записи будет применять всё это тяжелое условие.
Ухищрения с условиями в конкретном случае - попытка выиграть жалкие проценты, в то время как можно ускорить работу на порядок, переписав запрос.
35 posq
 
06.10.14
14:09
Еще возник вопрос абстрагируясь от сути(таблицы только как пример): Какой запрос будет работать быстрее?
Верно ли я понимаю, что второй случай лучше т.к. мы сначала выберем необходимые данные по отборам, а потом их свяжем. В первом же сначала произойдет соединение всех записей в таблице, а потом уже проверка на соответствие отборам? Это же очевидно или я очень сильно заблуждаюсь?)


Мой вариант 1:
ВЫБРАТЬ
    ДомаПоДоговору.Дом КАК Дом,
    ДоговорыЖКХ.Ссылка,
    ДоговорыЖКХ.Сумма КАК Сумма,
    ДоговорыЖКХ.ПредметДоговора КАК ПредметДоговора,
    ДоговорыЖКХ.НомерДоговора,
    ДоговорыЖКХ.ДатаДоговора
ИЗ
    Справочник.ДоговорыЖКХ.Дома КАК ДомаПоДоговору
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ДоговорыЖКХ КАК ДоговорыЖКХ
        ПО ДомаПоДоговору.Ссылка = ДоговорыЖКХ.Ссылка
ГДЕ
    ДомаПоДоговору.Дом = &Дом
    И ДоговорыЖКХ.Владелец = &ЖКХ
/////////////////////////////////////////////////////////////////////



Мой вариант 2:
ВЫБРАТЬ
    ДоговорыПоЖКХ.Ссылка,
    ДоговорыПоЖКХ.Сумма,
    ДоговорыПоЖКХ.ПредметДоговора,
    ДоговорыПоЖКХ.НомерДоговора,
    ДоговорыПоЖКХ.ДатаДоговора
ИЗ
    (ВЫБРАТЬ
        ДомаПоДоговору.Ссылка КАК Ссылка
    ИЗ
        Справочник.ДоговорыЖКХ.Дома КАК ДомаПоДоговору
    ГДЕ
        ДомаПоДоговору.Дом = &Дом) КАК ДоговорыПоДому
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
            ДоговорыЖКХ.Ссылка КАК Ссылка,
            ДоговорыЖКХ.Сумма КАК Сумма,
            ДоговорыЖКХ.ПредметДоговора КАК ПредметДоговора,

            ДоговорыЖКХ.НомерДоговора КАК НомерДоговора,
            ДоговорыЖКХ.ДатаДоговора КАК ДатаДоговора
        ИЗ
            Справочник.ДоговорыЖКХ КАК ДоговорыЖКХ
        ГДЕ
            ДоговорыЖКХ.Владелец = &ЖКХ) КАК ДоговорыПоЖКХ
        ПО ДоговорыПоДому.Ссылка.Ссылка = ДоговорыПоЖКХ.Ссылка
36 КонецЦикла
 
06.10.14
14:13
SQL умнее тебя. Он сделает все так как ты и не догадывался.
А если серьезно - найди время и возможность посмотреть лично планы выполнения запросов, не ипи моск.
37 hhhh
 
06.10.14
14:18
(35) по любому

ПО ДоговорыПоДому.Ссылка.Ссылка

в 10 раз медленнее чем

ПО ДоговорыПоДому.Ссылка

Зачем вы влезаете в какие-то тонкости, если элементарное не можете освоить?
38 posq
 
06.10.14
14:19
(37) Это описка. И так ясно. Просто скопировал из первого поста.
39 posq
 
06.10.14
14:23
(36) Ок. Я понимаю что оптимизатор запроса сам напишет как лучше. Очевидная же вещь. В Первом случае у нас сначала будет соединение двух полных таблиц, а потом отбор? Или ситуация такая что делать можно как хочешь и хрен проссышь как этот запрос на SQL переведется?
40 posq
 
06.10.14
14:24
(37)В конструкторе по быстрому накидывал вот и вылезла ссылка.
41 hhhh
 
06.10.14
14:31
всё-таки

ВЫБРАТЬ
    ДомаПоДоговору.Дом КАК Дом,
    ДомаПоДоговору.Ссылка,
    ДомаПоДоговору.Ссылка.Сумма КАК Сумма,
    ДомаПоДоговору.Ссылка.ПредметДоговора КАК ПредметДоговора,
    ДомаПоДоговору.Ссылка.НомерДоговора,
    ДомаПоДоговору.Ссылка.ДатаДоговора
ИЗ
    Справочник.ДоговорыЖКХ.Дома КАК ДомаПоДоговору

ГДЕ
    ДомаПоДоговору.Дом = &Дом
    И ДомаПоДоговору.Ссылка.Владелец = &ЖКХ
42 floody
 
06.10.14
14:34
Оригинал конечно лучше, читабельность тоже важна.
Вот если запрос реально тормозит, тогда да, в топку читабельность.
43 hhhh
 
06.10.14
14:36
(39) похоже вы забыли указать у поля ДомаПоДоговору.Дом свойство "Индексировать". Из-за этого и пристаете к нам со всякой лабудой.
44 posq
 
06.10.14
14:40
Я про конкретику не говорю. Просто пример абстрактных двух таблиц с огромным количеством данных, я ни с чем не пристаю пытаюсь понять как лучше, быстрее, логичнее и в последнюю очередь читабельнее.
Да, в курсе что индексы важны, по владельцу, вон есть индекс.
Сейчас вопрос стоит в (35).
45 hhhh
 
06.10.14
14:42
(44) ну за вложенные запросы по-любому на экзамене расстреливают. Прям из калаша вгоняют 150 пуль. Чтобы больше не писал.
46 Sammo
 
06.10.14
14:49
(42) Мне наоборот читабельнее запрос с соединением :)
47 Hans
 
06.10.14
14:52
Не надо мудрить, оставьте оригинал, он читабельный.
48 sf
 
06.10.14
14:52
(44) то, что первый запрос быстрее будет, было уже?
49 posq
 
06.10.14
15:13
(44) Да.
(45) Да я в одном месте слышал что под временную таблицу создается создается реальная таблица, а это время и ресурсы, в другом месте что оптимизатор нормально не сможет вычислить количество получаемых записей в таблице формируемой подзапросом и оптимально построить запрос для соединения таблиц.
В случае если есть соединение, то необходимо пользоваться временными таблицами. Верно?
50 sf
 
06.10.14
15:24
(49) В случае если есть соединение, то необходимо пользоваться временными таблицами.

имхо, в этом случае надо обратно в книжки учить терминологию. и не фантазировать по поводу как себя поведет скуль. хотя это тоже было, да?
51 DexterMorgan
 
06.10.14
15:50
(50) "и не фантазировать по поводу как себя поведет скуль"
именно поэтому в книжках и рекомендуют вместо соединений с вложенными запросами или виртуальными таблицами использовать временные таблицы
52 sf
 
06.10.14
15:53
(51) что? задачу в (0) еще и через временные таблицы можно решить? :D
53 roman52
 
06.10.14
21:30
ВЫБРАТЬ
    ДомаПоДоговору.Дом КАК Дом,
    ДоговорыЖКХ.Ссылка,
    ДоговорыЖКХ.Сумма КАК Сумма,
    ДоговорыЖКХ.ПредметДоговора КАК ПредметДоговора,
    ДоговорыЖКХ.НомерДоговора,
    ДоговорыЖКХ.ДатаДоговора
ИЗ
    Справочник.ДоговорыЖКХ.Дома КАК ДомаПоДоговору
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ДоговорыЖКХ КАК ДоговорыЖКХ
        ПО ДомаПоДоговору.Ссылка = ДоговорыЖКХ.Ссылка
            И ДомаПоДоговору.Дом = &Дом
            И ДоговорыЖКХ.Владелец = &ЖКХ

имхо куда уж быстрее..
54 User_Agronom
 
06.10.14
21:43
(15)...Но у Чистова на сайте и не только у него слышал что если пишем обращение через точку СУБД его превратит в соединение...

Интересно,откуда у Чистова такие выводы?

(15)...что если пишем, то лучше самим написать обращение к таблице...

Чушь чистой воды, особенно если первая часть (про превращение в соединение) правда.
55 КонецЦикла
 
06.10.14
21:44
(54) А во что можно еще превратить точку?
56 roman52
 
06.10.14
21:49
(54) СУБД обращение через точку в любом случае превратит в левое соединение

а сам можеть написать через внутреннее

разницу чуйствуешь?
57 User_Agronom
 
06.10.14
21:59
(56) Ссыль на сайт разработчиков СУБД. MS или Postgre. На основании чего были сделаны такие выводы?
58 MrStomak
 
06.10.14
22:06
(57) Зачем тебе ссыль на разработчиков СУБД, в языках которых никакого "обращения через точку" вообще не допустимо?

Попробуй через точку поле регистратора у вт ОстаткиИОбороты получить и объяснить, как без левого соединения там null могут быть.
А еще лучше просто посмотреть в профайлере.
59 User_Agronom
 
06.10.14
22:14
http://technet.microsoft.com/ru-ru/magazine/2007.11.sqlquery.aspx

SELECT c.CustomerID, SUM(LineTotal)
FROM Sales.SalesOrderDetail od
JOIN Sales.SalesOrderHeader oh
ON od.SalesOrderID=oh.SalesOrderID
JOIN Sales.Customer c ON oh.CustomerID=c.CustomerID
GROUP BY c.CustomerID

я вижу точку. Как это соотносится с (58)...в языках которых никакого "обращения через точку" вообще не допустимо?...

?

И сайт не жёлтой прессы;)
60 MrStomak
 
06.10.14
22:31
(59) Ну давай покажи, где ты тут увидел "обращение через точку".
61 roman52
 
06.10.14
22:56
(57) пардоньте, не СУБД, а движок 1С при трансляции запросов 1С в запросы СУБД
а вообще лучше один раз увидеть...
профайлер в руки и впердё - все вопросы должны отпасть
62 User_Agronom
 
07.10.14
08:43
(60) SELECT c.CustomerID
63 roman52
 
07.10.14
20:40
(60)
http://www.fedupusa.org/wp-content/uploads/2013/11/1314029819767.png

еще раз, прогони запросы ТС-а через профайлер и посмотри получающиеся тексты запросов SQL - все прояснится
64 roman52
 
07.10.14
20:41
(63) к (62)
65 Drac0
 
07.10.14
20:48
(62) Это не "обращение через точку". Это обращение к полю "CustomerID" таблицы с псевдонимом "с". А вот если бы там было что-то типа с.Customer.Name, тогда да. Странно, что ты это не понимаешь.