К списку форумов К списку тем
Регистрация    Правила    Главная форума    Поиск   
Имя: Пароль:
Рекомендовать в новости

Какой запрос будет требовать меньше ресурсов?

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
Цитата:
Сообщение от bma1 Посмотреть сообщение
Он сперва делает отбор по первому условию, а потом внутреннее соединение по второму.
В смысле. Он сперва из регистра делает отбор по первому условию в ПО, а потом результат соединяет с таблицей документа про условию во второй строке условия ПО.
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, особенно когда есть возможность соединить по индексу. Так что зачастую В() и ВНУТРЕННЕЕ СОЕДИНЕНИЕ равнозначны.


К списку вопросов






Copyright ©, Все права защищены