Какой запрос будет требовать меньше ресурсов? Есть две таблицы, которые связываются по соединению с условием разными вариантами: 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.ССылкаНаСсылку Вот здесь и возникли сомнения. Будет ли третий вариант быстрее и менее ресурсоемким чем второй или они одинаковы... |
какой sql сервер, какая версия, собрана ли статистика, какие индексы, сколько оперативной памяти :) не угадаешь |
+1 что говорит план запроса во всех 3-х случаях? а если будет рлс? |
2(2) План запросов выдает во всех трех случаях длииинные простынки. запрос будет работать редко, потому статистика будет искажена чуть реже чем всегда, но хочется чтоб пользователю было как можно менее напряжно. А запрос как раз для rls. На каком сервере будет эта байда стоять - вопрос и для меня, я отлаживаю на чем есть - mssql2008r2. |
(3) то есть намек не понял, толку от того что ты подберешь лучший запрос на своем компе, никакой гарантии что он так же будет работать в реальности. Более того теоретически скл сервер должен для всех эквивалентных запросов делать одинаковый наиболее выгодный план |
2(4) запросы не совсем эквивалентны. например 1ый запрос не годится, если надо получить спарва значения NULL, на отстутствующие значения. Поэтому sql посторит в принципе разные запросы. |
Хм... с другой стороны СОЕДИНЕНИЕ и подзапрос не рекомендованное сочетание, во всяком случае так было раньше, вот что-то не припомню, кажется в последних релизах писалось про оптимизацию этой ситуации в движке 1с или нет? |
Скуль - умный. Без хинтов ему по барабану, какой вариант из этих трёх ты ему предложишь. Он всё равно, в зависимости от ситуации, придумает свой собственный. Так что не парься, оставляй какой тебе больше нравится. :) |
я пока склоняюсь ко второму варианту... |
На текущем этапе своего развития я нахожу наиболее гармоничным и сбалансированным второй вариант. |
Вот смотрю на запрос 1 и 2 и почему то мне кажется что у них будет разный результат |
не обратил внимание на пару верхних сообщений, сорри |
2(1) "собрана ли статистика" - шутишь? Статистику надо собирать каждый день, более того и пытаться переиндексировать таблицы тоже, это взаимосвязанные вещи, sql-сервер оперирует страницами данных. Неплохо включить появившуюся в 2005 возможность версионности записей - ускорит запись, чтение замедлит незаметно. Пересчитывать итоги так же лучше каждую ночь, но это уже не получается, хотя бы перед серьезным оперированием ими. |
+(12) Что касается запросов - не занимайтесь фигней пишите через точку, толку от того, что выполнение запроса выиграло пару секунд, который нужен раз в пятилетку. Вот, когда предполагается запись данных, тогда да, стоит с этим разбираться и оптимизировать всеми возможными средствами. |
2(0) Это загадка, ответ на который тебе никто не даст - сначала 1с транслирует запрос, потом сервер приложений еще подумает, как его лучше скэшировать, а уж затем он попадет на sql-сервер, который почешет репу от всего навалившегося и сделает еще одну глупость согласно как раз той самой статистики. |
2(14) Это все верно, только это не повод писать запросы абы как. Здесь как раз операция чтения критична, так как это будет rls на журнал. Лишняя пара даже не миллисекунд а целых секунд при записи не будет заметна на фоне кучи интерактивных проверок типа "а такой реквизит не забыли заполнить?". P.S. вот... почти намертво завесил 1с-ку запросом с конструкцией ПО (ВЫБОР КОГДА таблица1.Реквизит = ЗНАЧЕНИЕ(Справочник.Некий.ПустаяСсылка) ТОГДА ИСТИНА ИНАЧЕ таблица1.Реквизит = таблица2.Реквизит КОНЕЦ) Вариант с ПО (таблица1.Реквизит = ЗНАЧЕНИЕ(Справочник.Некий.ПустаяСсылка) ИЛИ таблица1.Реквизит = таблица2.Реквизит) работает значительно быстрее. |
поиграться на своем компе всегда полезно! 1) ВАРИАНТ теоретически - мимо, слабоват. На больших объемах просядет. 2 или 3 - надо засекать на конкретных примерах. Предложу 4 - пакетный запрос. 4) Выборка по временную таблицу - подзапрос Ну и соединение по ссылке |
2(16) в обычном случае пакетный подошел бы идеально, но тут запрос для rls, там особо не побалуешься... P.S. хотя непонятно, почему в (15) такая разница во времени исполнения... вроде смысл в обоих условиях одинаков - сперва сравнить с пустым значением и дальше получив ИСТИНА не проверять следующее условие... |
ветвление всегда более сложная операция чем логические |
В RLS вообще не кошерно использовать соединения. Гораздо приятнее (а по производительности идентично или даже лучше) использовать конструкции ГДЕ 1 В ( ВЫБРАТЬ ПЕРВЫЕ 1 1 ИЗ... ГДЕ... ) Если для тебя не важно отличие результатов выполнения запросов 1 и 2 - бери 1й вариант. В нем будет выполнена трансляция из ЛЕВОГО во ВНУТРЕННЕЕ соединение, что слегка производительнее ЛЕВОГО. ПЫСЫ: Вообще писать ЛЕВОЕ СОЕДИНЕНИЕ в первом запросе - жуткий моветон. Вроде бы и ЛЕВОЕ, а работает полностью как ВНУТРЕННЕЕ. Это ухудшает читаемость кода. |
(15) Конструкция ВЫБОР никогда не учитывается при построении плана выполнения запроса, а накладывается сверху. В отличии от этого, условие по ИЛИ очень даже понятно SQL при определении порядка выборки. Мы напоролись на такую тему при разборках с 1С по поводу тормозов динамического списка управляемых форм. В каждом релизе обещают исправить, но по данным последней переписки опять отодвинули на 8.3.4 :-( Задолбали |
2(19) в окончательном варианте запрос будет переписываться на внутреннее соединение, которое несколько эффективнее конструкции В(ВЫБРАТЬ...) по скорости. А сейчас это тестовые варианты. |
(21) В большинстве случаев, внутреннее соединение и В(ВЫБРАТЬ) приводят к полностью идентичному плану выполнения. Мои разработчики приводили некоторые примеры, где действительно соединение оказывается получше. Но это было гораздо более сложные запросы, нежели в этом случае. На время теста, до передачи в производство, именно в RLS, все таки я бы рекомендовал именно В(ВЫБРАТЬ...) как основной подход к написанию запроса. Так мы показываем, какие именно критерии накладываем на каждую строку. А на этапе отладки можно каждый из таких критериев отдельно проверять, просто комментируя ветку "ИЛИ..." |
ИМХО, зависит от статистики: Что больше ограничивает выборку по второй таблице - "Поле" или "СсылкаНаСсылку"? |
Так, что выяснилось из сбора информации по разным форумам (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 = &НекоеЗначение" и иногда быстрее. Причины не всегда понятны, что-то больно мудрят оптимизаторы планов запросов. |
Проверил два варианта: 1-ый вариант: ВЫБРАТЬ Т.Ссылка ИЗ Документ.НекийДокумент КАК Т ГДЕ ИСТИНА В (ВЫБРАТЬ ПЕРВЫЕ 1 ИСТИНА ИЗ РегистрСведений.НекийРегистр КАК Д ГДЕ Д1.РеквизитЗн = &Значение И Д1.Реквизит = Т.Реквизит1) 2-ой вариант: ВЫБРАТЬ Т.Ссылка ИЗ Документ.НекийДокумент КАК Т ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.НекийРегистр КАК Д ПО Д.РеквизитЗн = &Значение И Д1.Реквизит = Т.Реквизит1 оказалось, что второй вариант действительно кушает меньше ресурсов. Он сперва делает отбор по первому условию, а потом внутреннее соединение по второму. А первый, для каждой строки таблицы с документами делает проверку в цикле по сформированным вложенным запросам с отбором по условиям. А при росте количества реквизитов, по которым происходит проверка - преимущество второго варианта только растет. Разница выходит в пределах 10% при пяти проверяемых реквизитах. |
[quote=bma1;31017972]Он сперва делает отбор по первому условию, а потом внутреннее соединение по второму.[/quote] В смысле. Он сперва из регистра делает отбор по первому условию в ПО, а потом результат соединяет с таблицей документа про условию во второй строке условия ПО. |
Сравнил варианты: 1-ый вариант ВЫБРАТЬ Т.Ссылка ИЗ Документ.НекийДокумент КАК Т ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.НекийРегистр КАК Д ПО (Т.Реквизит = Д.Реквизит ИЛИ Т.Реквизит = ЗНАЧЕНИЕ(Справочник.НекийСправочник.ПустаяСсылка)) и 2-ой вариант ВЫБРАТЬ Т.Ссылка ИЗ Документ.НекийДокумент КАК Т ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ЗНАЧЕНИЕ(Справочник.НекийСправочник.ПустаяСсылка) КАК Реквизит ОБЪЕДИНИТЬ ВЫБРАТЬ Д.Реквизит ИЗ РегистрСведений.НекийРегистр КАК Д) КАК Д ПО Т.Реквизит = Д.Реквизит Второй вариант быстрее от 10 до 100 раз. Я в задумчивости... |
27-bma1 >Даже и не задумывайся, можно сказать - баян :) [url]http://forums.kuban.ru/f1040/ut10_3_u_kogo_problemy_so_skorost-yu_spisaniya_partij_hod-_syudy-2892325.html[/url] |
2(28) Не, задуматься стоит. Т.к. 1. у тебя объединение пустой ссылки икороткого справочника "Склады", а я делал объединение пустой строки и длинного справочника "Контрагенты" 2. конструкция с ВНУТРЕННЕЕ СОЕДИНЕНИЕ, как показал план запросов в SQL, меньше занимает времени чем конструкция с В() |
29-bma1 >1. Тут важно не то с чем объединяем, а наличие - отсутствие ИЛИ. 2. Как я уже писал ранее, скуль умный, и зачастую оптимизатор подменяет WHERE VAL IN (SELECT ... ) на INNER JOIN, особенно когда есть возможность соединить по индексу. Так что зачастую В() и ВНУТРЕННЕЕ СОЕДИНЕНИЕ равнозначны. |
Текущее время: 19:03. Часовой пояс GMT +3. |