FB 2.5: параметр в where

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
VerLeon
Сообщения: 44
Зарегистрирован: 24 ноя 2007, 08:43

FB 2.5: параметр в where

Сообщение VerLeon » 31 янв 2009, 12:43

Вот какую штуку обнаружил (заранее прошу прощения, если в трекере такое есть)

Выполняем запрос:

Код: Выделить всё

select * from t1 where :param = 1
При любом значении параметра шерстится вся таблица. А зачем?
Собственно так было и в IB, и я к этому привык, как к неизбежному злу, но в FB я обнаружил вот что:

Код: Выделить всё

select * from rdb$database left join t1 on :param = 1
В IB разницы нет - все равно пройдет всю таблицу. В FB - ура! Если параметр не равен единице к t1 обращения не будет!
Значит оптимизатор это может все-таки обрабатывать? Но почему тогда в where не может?
Нет, я понимаю, что условия в on и условия в where - это разные вещи и обрабатываться должны по-разному, но в данном конкретном примере - какая разница?

В общем это не проблема, я таким джойнами теперь все и разруливаю, где мне надо, но ведь некрасиво и нелогично...

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Re: FB 2.5: параметр в where

Сообщение kdv » 02 фев 2009, 11:29

сначала строится план запроса, а только ПОТОМ - выполняется с полученными параметрами.
Т.е. на этапе построения плана сервер не знает, что будет в параметре. В FB 2.5 к исправлению подобных ситуаций были приняты меры, об этом надо смотреть в release notes по 2.5.
Статья о методах доступа - тут
www.ibase.ru/devinfo/dataaccesspaths.htm

VerLeon
Сообщения: 44
Зарегистрирован: 24 ноя 2007, 08:43

Re: FB 2.5: параметр в where

Сообщение VerLeon » 02 фев 2009, 12:43

Так я про планы и не говорю. Планы в части таблицы t1 будут одинаковыми (натуралы) в обоих случаях, что вполне понятно.
Отличаются эти запросы статистикой выполнения - в первом будут профетчены все записи из t1, во-втором при param <> 1 - ни одной.
Если я правильно понимаю механизм выполнения соединений, то во втором запросе будет применен алгоритм однопроходного слияния - должно строиться бинарное дерево слияния и при фетче анализироваться ключи. Но фетча из второго потока (t1) не происходит - хотя в первом потоке при любом значении параметра будет одна запись, он не будет пустой (прошу заметить, что условие во втором запросе стоит не в where, а именно в on). Значит сервер понял, что фетч бессмысленен (видимо после построения дерева слияния, которое по сути пустое получилось)? Т.е. при слиянии ПЕРЕД ФЕТЧЕМ такую проверку сделать можно и она реализована (за что большое спасибо). Но почему бы не сделать то же самое перед простым фетчем по where? Т.е. выделять предикаты, которые не зависят от фильтруемого потока из собственно фильтра и проверять их до фетча, а не после.

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

P.S. статью я читал, очень полезная статья

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Re: FB 2.5: параметр в where

Сообщение WildSery » 02 фев 2009, 13:06

VerLeon писал(а):P.S. статью я читал, очень полезная статья
Видимо, недостаточно хорошо, иначе бы не говорил об "однопроходном слиянии" в случае LEFT JOIN.

VerLeon
Сообщения: 44
Зарегистрирован: 24 ноя 2007, 08:43

Re: FB 2.5: параметр в where

Сообщение VerLeon » 02 фев 2009, 13:50

WildSery писал(а):Видимо, недостаточно хорошо, иначе бы не говорил об "однопроходном слиянии" в случае LEFT JOIN.
Да, ступил... Никогда раньше таких джойнов не делал, чтоб прицепляемая таблица не зависела от главной, посчитал в этом случае потоки независимыми :)
Но разве это что-то меняет?

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Re: FB 2.5: параметр в where

Сообщение WildSery » 02 фев 2009, 21:56

VerLeon писал(а):Но разве это что-то меняет?
Никто и не опровергает, что ты прав. Да, есть ещё куда развиваться оптимизатору :)

Хотя, такие ситуации "исправлять" нужно ИМХО в последнюю очередь - очень уж искусственный и надуманый запрос. Не буду гадать, почему везде применяешь, ведь легко заменяется на проверку+запрос в PSQL.

Ответить