Страница 1 из 1

порядок джоинов в фб 1.5

Добавлено: 05 мар 2007, 15:11
entryway
Всегда удивляло в фаирберде как каждый раз в запросах приходится "подбирать" порядок джоинов для быстрого выполнения. Причем на мой неопытный глаз именно "подбирать" - логику проследить сложно. Во всяком случае мне. То лефт джоины вверх вытягивать помогает (!?), то наоборот. Но сегодня и вовсе натолкнулся на смешной случай:

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

select ...
from infosms s
inner join sms_states on sms_states.id = s.state
left join operators o1 on o1.id = s.operator_id
left join operators o2 on o2.id = s.assigned_operator_id
inner join sms_services on sms_services.id = s.service_id
where (sms_states.doshow = 1) and (s.pendingstate = 0)
Запрос выполняется мгновенно (выбирается одна запись). Если переставить последний иннер на второе или первое место - запрос выполняется секунду. Но самое смешное дальше: если убить два лефт джоина, то уже никакой порядок оставшихся двух иннеров не будет выполнять запрос мгновенно. То есть просто добавление в запрос мусора вида:

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

left join operators o1 on o1.id = s.operator_id
left join operators o2 on o2.id = s.assigned_operator_id
ускорят запрос.

Что я делаю не так?

Добавлено: 05 мар 2007, 15:26
kdv
объясните, пожалуйста:
в states могут быть состояния, которых нет в Operators, и их надо выбрать все? как в отношении s.operator_id, так и s.assigner_operator ?

статью www.ibase.ru/devinfo/joins.htm читали?

Добавлено: 05 мар 2007, 15:44
entryway
Внимательно посмотрите запрос. Мне кажется вы попутали. s - это алиас на infosms, а не на sms_states. operator_id и assigned_operator_id естественно могут быть нулом, потому и лефт. В infosms нет записей со state которым нет соответствия в sms_states. В sms_states 5 записей, 3 из них с doshow == 1, две с 0.

Добавлено: 05 мар 2007, 15:54
kdv
ok. при left/right join таблицы обычно идут в плане так, как это указано в запросе. Поэтому желательно приводить не только запрос, но и план, также статистику запроса (время, reads, fetches - как минимум).

ответ понятен, но частично - в infosms есть записи, которым нет соответствия в operators по s.operator_id ? Грубо говоря, я хочу ясный ответ - Вы понимаете работу left join? Т.е. пишете их в запросе осознанно?
Примерно половина вопросов про left join - от "автоматизированных построителей" или непонимания.

p.s. поясняю. когда Вы пишете a left join b - в a выбираются все записи. Если "переставить последний иннер на второе или первое место" - вначале сервер выполнит совершенно другую работу, чем при перестановке таблиц. Чем больше записей выбираются таким способом - тем хуже время, например.

Re: порядок джоинов в фб 1.5

Добавлено: 05 мар 2007, 15:55
Merlin
entryway писал(а):Всегда удивляло в фаирберде как каждый раз в запросах приходится "подбирать" порядок джоинов для быстрого выполнения. Причем на мой неопытный глаз именно "подбирать" - логику проследить сложно.
Проще пареной репы. Иннер-объединения должны выполняться в такой последовательности, чтобы максимизировать усечение ими перебора длинных таблиц.
entryway писал(а): Во всяком случае мне. То лефт джоины вверх вытягивать помогает (!?), то наоборот.
Это из области "то их понюхает, то их полижет" (С). Лефт нужен там, где он нужен. Порядком иннер-объединений надо рулить при помощи хинтов +0 или секцией Plan.

entryway писал(а): то уже никакой порядок оставшихся двух иннеров не будет выполнять запрос мгновенно.
Под порядком иннеров понимаем порядок их записи собственными палчиками? Напрасно, напрасно... Порядок надо в плане запроса смотреть.

Добавлено: 05 мар 2007, 15:57
kdv
Под порядком иннеров понимаем порядок их записи
замечу, что я имел в виду порядок при left. про запрос с только inner я ничего не говорил :-) В любом случае план надо смотреть.

Re: порядок джоинов в фб 1.5

Добавлено: 05 мар 2007, 16:11
dimitr
entryway писал(а):Что я делаю не так?
используешь 1.5?

Добавлено: 05 мар 2007, 16:25
entryway
ответ понятен, но частично - в infosms есть записи, которым нет соответствия в operators по s.operator_id ?
да, в infosms бывают нулы.
Вы понимаете работу left join?
Разумеется.
Т.е. пишете их в запросе осознанно?
Ага.
Примерно половина вопросов про left join - от "автоматизированных построителей" или непонимания.
Я к ним не отношусь и построителей в глаза не видел.
Лефт нужен там, где он нужен
Вот пристали :) Он мне нужен! Именно там и так как я написал. И должен по логике быть внизу, после иннеров, так как ничего не отсекают. Но фича не в этом, фича в том, что если их убрать - время выполнения запроса увеличивается многократно. Считаю такое поведение - ошибкой в оптимизаторе, не иначе. Суть поста именно в этом. Надо бы проверить на 2.0. План в последнем случае такой: PLAN JOIN (S INDEX (INFOSMS_IDX8),SMS_STATES INDEX (PK_SMS_STATES,SMS_STATES_DOSHOW),SMS_SERVICES INDEX (PK_SMS_SERVICES)), где INFOSMS_IDX8 - индекс по pendingstate. Убиение индекса SMS_STATES_DOSHOW (созданного с утра в отчаянье) решило "проблему двух иннеров"

Re: порядок джоинов в фб 1.5

Добавлено: 05 мар 2007, 16:29
entryway
dimitr писал(а):
entryway писал(а):Что я делаю не так?
используешь 1.5?
Да я практически уверен, что проблема именно в этом, но так как по глупости наплодил давным-давно кучу процедур в которых таблицы используются одновременно и по алиасу и по полному имени, то переход на 2.0 выглядит слегка проблематичным. Вот так и терплю до сих пор, блин.