0
- 20.06.2013 - 14:11
|
Есть две таблицы, которые связываются по соединению с условием разными вариантами: 1. ... ИЗ таблица1 КАК Т1 ЛЕВОЕ СОЕДИНЕНИЕ таблица2 КАК Т2 ПО Т1.Ссылка = Т2.ССылкаНаСсылку ГДЕ Т2.Поле = &Поле Здесь, насколько я знаю, худший вариант, так как сперва все выбирается из таблицы2, потом всё соединяется по условию и только потом происходит отбор Поэтому можно использовать два варианта 2. ... ИЗ таблица1 КАК Т1 ЛЕВОЕ СОЕДИНЕНИЕ таблица2 КАК Т2 ПО Т1.Ссылка = Т2.ССылкаНаСсылку И (Т2.Поле = &Поле) 3. ... ИЗ таблица1 КАК Т1 ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ТЗ2.ССылкаНаСсылку ИЗ таблица2 КАК Т2 ГДЕ Т2.Поле = &Поле) КАК Т2 ПО Т1.Ссылка = Т2.ССылкаНаСсылку Вот здесь и возникли сомнения. Будет ли третий вариант быстрее и менее ресурсоемким чем второй или они одинаковы... | |
1
- 20.06.2013 - 14:16
|
какой sql сервер, какая версия, собрана ли статистика, какие индексы, сколько оперативной памяти :) не угадаешь | |
2
- 20.06.2013 - 14:16
| +1 что говорит план запроса во всех 3-х случаях? а если будет рлс? | |
3
- 20.06.2013 - 14:35
| 2(2) План запросов выдает во всех трех случаях длииинные простынки. запрос будет работать редко, потому статистика будет искажена чуть реже чем всегда, но хочется чтоб пользователю было как можно менее напряжно. А запрос как раз для rls. На каком сервере будет эта байда стоять - вопрос и для меня, я отлаживаю на чем есть - mssql2008r2. | |
4
- 20.06.2013 - 14:44
|
(3) то есть намек не понял, толку от того что ты подберешь лучший запрос на своем компе, никакой гарантии что он так же будет работать в реальности. Более того теоретически скл сервер должен для всех эквивалентных запросов делать одинаковый наиболее выгодный план | |
5
- 20.06.2013 - 14:51
|
2(4) запросы не совсем эквивалентны. например 1ый запрос не годится, если надо получить спарва значения NULL, на отстутствующие значения. Поэтому sql посторит в принципе разные запросы. | |
6
- 20.06.2013 - 15:53
| Хм... с другой стороны СОЕДИНЕНИЕ и подзапрос не рекомендованное сочетание, во всяком случае так было раньше, вот что-то не припомню, кажется в последних релизах писалось про оптимизацию этой ситуации в движке 1с или нет? | |
7
- 20.06.2013 - 17:48
|
Скуль - умный. Без хинтов ему по барабану, какой вариант из этих трёх ты ему предложишь. Он всё равно, в зависимости от ситуации, придумает свой собственный. Так что не парься, оставляй какой тебе больше нравится. :) | |
8
- 20.06.2013 - 18:22
| я пока склоняюсь ко второму варианту... | |
9
- 20.06.2013 - 20:16
| На текущем этапе своего развития я нахожу наиболее гармоничным и сбалансированным второй вариант. | |
10
- 20.06.2013 - 21:29
| Вот смотрю на запрос 1 и 2 и почему то мне кажется что у них будет разный результат | |
11
- 20.06.2013 - 21:46
| не обратил внимание на пару верхних сообщений, сорри | |
12
- 21.06.2013 - 00:00
| 2(1) "собрана ли статистика" - шутишь? Статистику надо собирать каждый день, более того и пытаться переиндексировать таблицы тоже, это взаимосвязанные вещи, sql-сервер оперирует страницами данных. Неплохо включить появившуюся в 2005 возможность версионности записей - ускорит запись, чтение замедлит незаметно. Пересчитывать итоги так же лучше каждую ночь, но это уже не получается, хотя бы перед серьезным оперированием ими. | |
13
- 21.06.2013 - 00:03
| +(12) Что касается запросов - не занимайтесь фигней пишите через точку, толку от того, что выполнение запроса выиграло пару секунд, который нужен раз в пятилетку. Вот, когда предполагается запись данных, тогда да, стоит с этим разбираться и оптимизировать всеми возможными средствами. | |
14
- 21.06.2013 - 00:05
| 2(0) Это загадка, ответ на который тебе никто не даст - сначала 1с транслирует запрос, потом сервер приложений еще подумает, как его лучше скэшировать, а уж затем он попадет на sql-сервер, который почешет репу от всего навалившегося и сделает еще одну глупость согласно как раз той самой статистики. | |
15
- 21.06.2013 - 07:33
|
2(14) Это все верно, только это не повод писать запросы абы как. Здесь как раз операция чтения критична, так как это будет rls на журнал. Лишняя пара даже не миллисекунд а целых секунд при записи не будет заметна на фоне кучи интерактивных проверок типа "а такой реквизит не забыли заполнить?". P.S. вот... почти намертво завесил 1с-ку запросом с конструкцией ПО (ВЫБОР КОГДА таблица1.Реквизит = ЗНАЧЕНИЕ(Справочник.Некий.ПустаяСсылка) ТОГДА ИСТИНА ИНАЧЕ таблица1.Реквизит = таблица2.Реквизит КОНЕЦ) Вариант с ПО (таблица1.Реквизит = ЗНАЧЕНИЕ(Справочник.Некий.ПустаяСсылка) ИЛИ таблица1.Реквизит = таблица2.Реквизит) работает значительно быстрее. | |
16
- 21.06.2013 - 09:15
|
поиграться на своем компе всегда полезно! 1) ВАРИАНТ теоретически - мимо, слабоват. На больших объемах просядет. 2 или 3 - надо засекать на конкретных примерах. Предложу 4 - пакетный запрос. 4) Выборка по временную таблицу - подзапрос Ну и соединение по ссылке | |
17
- 21.06.2013 - 09:54
|
2(16) в обычном случае пакетный подошел бы идеально, но тут запрос для rls, там особо не побалуешься... P.S. хотя непонятно, почему в (15) такая разница во времени исполнения... вроде смысл в обоих условиях одинаков - сперва сравнить с пустым значением и дальше получив ИСТИНА не проверять следующее условие... | |
18
- 21.06.2013 - 10:38
| ветвление всегда более сложная операция чем логические | |
19
- 21.06.2013 - 14:40
|
В RLS вообще не кошерно использовать соединения. Гораздо приятнее (а по производительности идентично или даже лучше) использовать конструкции ГДЕ 1 В ( ВЫБРАТЬ ПЕРВЫЕ 1 1 ИЗ... ГДЕ... ) Если для тебя не важно отличие результатов выполнения запросов 1 и 2 - бери 1й вариант. В нем будет выполнена трансляция из ЛЕВОГО во ВНУТРЕННЕЕ соединение, что слегка производительнее ЛЕВОГО. ПЫСЫ: Вообще писать ЛЕВОЕ СОЕДИНЕНИЕ в первом запросе - жуткий моветон. Вроде бы и ЛЕВОЕ, а работает полностью как ВНУТРЕННЕЕ. Это ухудшает читаемость кода. | |
20
- 21.06.2013 - 14:43
|
(15) Конструкция ВЫБОР никогда не учитывается при построении плана выполнения запроса, а накладывается сверху. В отличии от этого, условие по ИЛИ очень даже понятно SQL при определении порядка выборки. Мы напоролись на такую тему при разборках с 1С по поводу тормозов динамического списка управляемых форм. В каждом релизе обещают исправить, но по данным последней переписки опять отодвинули на 8.3.4 :-( Задолбали | |
21
- 21.06.2013 - 15:52
| 2(19) в окончательном варианте запрос будет переписываться на внутреннее соединение, которое несколько эффективнее конструкции В(ВЫБРАТЬ...) по скорости. А сейчас это тестовые варианты. | |
22
- 21.06.2013 - 16:32
|
(21) В большинстве случаев, внутреннее соединение и В(ВЫБРАТЬ) приводят к полностью идентичному плану выполнения. Мои разработчики приводили некоторые примеры, где действительно соединение оказывается получше. Но это было гораздо более сложные запросы, нежели в этом случае. На время теста, до передачи в производство, именно в RLS, все таки я бы рекомендовал именно В(ВЫБРАТЬ...) как основной подход к написанию запроса. Так мы показываем, какие именно критерии накладываем на каждую строку. А на этапе отладки можно каждый из таких критериев отдельно проверять, просто комментируя ветку "ИЛИ..." | |
23
- 23.06.2013 - 15:18
|
ИМХО, зависит от статистики: Что больше ограничивает выборку по второй таблице - "Поле" или "СсылкаНаСсылку"? | |
24
- 24.06.2013 - 16:27
|
Так, что выяснилось из сбора информации по разным форумам (1С, MSSQL, MySQL) и чтения MSDNов. 1. Конструкция "ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПО таблица1.Реквизит1 = таблица2.Реквизит1 И таблица1.Реквизит2 = &НекоеЗначение" выполняется всегда не медленнее чем конструкция "ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПО таблица1.Реквизит1 = таблица2.Реквизит1 ГДЕ таблица1.Реквизит2 = &НекоеЗначение" и иногда быстрее. 2. конструкция "ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПО таблица1.Реквизит2 = &НекоеЗначение И таблица1.Реквизит1 = таблица2.Реквизит1" выполняется всегда не медленне чем конструкция "ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПО таблица1.Реквизит1 = таблица2.Реквизит1 И таблица1.Реквизит2 = &НекоеЗначение" и иногда быстрее. Причины не всегда понятны, что-то больно мудрят оптимизаторы планов запросов. | |
25
- 25.06.2013 - 11:05
|
Проверил два варианта: 1-ый вариант: ВЫБРАТЬ Т.Ссылка ИЗ Документ.НекийДокумент КАК Т ГДЕ ИСТИНА В (ВЫБРАТЬ ПЕРВЫЕ 1 ИСТИНА ИЗ РегистрСведений.НекийРегистр КАК Д ГДЕ Д1.РеквизитЗн = &Значение И Д1.Реквизит = Т.Реквизит1) 2-ой вариант: ВЫБРАТЬ Т.Ссылка ИЗ Документ.НекийДокумент КАК Т ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.НекийРегистр КАК Д ПО Д.РеквизитЗн = &Значение И Д1.Реквизит = Т.Реквизит1 оказалось, что второй вариант действительно кушает меньше ресурсов. Он сперва делает отбор по первому условию, а потом внутреннее соединение по второму. А первый, для каждой строки таблицы с документами делает проверку в цикле по сформированным вложенным запросам с отбором по условиям. А при росте количества реквизитов, по которым происходит проверка - преимущество второго варианта только растет. Разница выходит в пределах 10% при пяти проверяемых реквизитах. | |
26
- 25.06.2013 - 11:08
| В смысле. Он сперва из регистра делает отбор по первому условию в ПО, а потом результат соединяет с таблицей документа про условию во второй строке условия ПО. | |
27
- 26.06.2013 - 08:33
|
Сравнил варианты: 1-ый вариант ВЫБРАТЬ Т.Ссылка ИЗ Документ.НекийДокумент КАК Т ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.НекийРегистр КАК Д ПО (Т.Реквизит = Д.Реквизит ИЛИ Т.Реквизит = ЗНАЧЕНИЕ(Справочник.НекийСправочник.ПустаяСсылка)) и 2-ой вариант ВЫБРАТЬ Т.Ссылка ИЗ Документ.НекийДокумент КАК Т ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ЗНАЧЕНИЕ(Справочник.НекийСправочник.ПустаяСсылка) КАК Реквизит ОБЪЕДИНИТЬ ВЫБРАТЬ Д.Реквизит ИЗ РегистрСведений.НекийРегистр КАК Д) КАК Д ПО Т.Реквизит = Д.Реквизит Второй вариант быстрее от 10 до 100 раз. Я в задумчивости... | |
28
- 26.06.2013 - 09:47
|
27-bma1 >Даже и не задумывайся, можно сказать - баян :) УТ10.3 У кого проблемы со скоростью списания партий, ходь сюды | |
29
- 26.06.2013 - 10:19
|
2(28) Не, задуматься стоит. Т.к. 1. у тебя объединение пустой ссылки икороткого справочника "Склады", а я делал объединение пустой строки и длинного справочника "Контрагенты" 2. конструкция с ВНУТРЕННЕЕ СОЕДИНЕНИЕ, как показал план запросов в SQL, меньше занимает времени чем конструкция с В() | |
30
- 26.06.2013 - 11:51
|
29-bma1 >1. Тут важно не то с чем объединяем, а наличие - отсутствие ИЛИ. 2. Как я уже писал ранее, скуль умный, и зачастую оптимизатор подменяет WHERE VAL IN (SELECT ... ) на INNER JOIN, особенно когда есть возможность соединить по индексу. Так что зачастую В() и ВНУТРЕННЕЕ СОЕДИНЕНИЕ равнозначны. | |
| Интернет-форум Краснодарского края и Краснодара |