Эта тема на forum.dklab.ru


zaartix: скорость выполнения запроса
Господа, подскажите пожалуйста какой запрос выполнится быстре?


select lev1cat.name as lev1Name, lev2cat.name as lev2Name, lev3cat.*
from site_exchange as ex, categories as lev1cat, categories as lev2cat, categories as lev3cat

left join site_base_pages as pages on ex.toBase=pages.baseId
left join site_base as sites on ex.fromBase=sites.id and sites.stats=1

where ex.fromBase='$baseId' and sites.id not in(
select fromBase from site_rejected where toBase='$baseId'
) and pages.id not in (
select toPage from site_exchange_pages where fromBase='$baseId'
)
and lev1cat.id=pages.l1cat and lev2cat.id=pages.l2cat and lev3cat.id=pages.catId and lev2cat.id='$cid' and pages.stats='1'
group by lev2cat.id

или этот:


select lev1cat.name as lev1Name, lev2cat.name as lev2Name, lev3cat.*
from site_exchange as ex

left join site_base_pages as pages on ex.toBase=pages.baseId
left join categories as lev1cat on lev1cat.id=pages.l1cat
left join categories as lev2cat on lev2cat.id=pages.l2cat and lev2cat.id='$cid'
left join categories as lev3cat on lev3cat.id=pages.catId
left join site_base as sites on ex.fromBase=sites.id and sites.stats=1

where ex.fromBase='$baseId' and sites.id not in(
select fromBase from site_rejected where toBase='$baseId'
) and pages.id not in (
select toPage from site_exchange_pages where fromBase='$baseId'
)
and pages.stats='1'
group by lev2cat.id


В первом случае 3 таблицы присутствуют в "from", во втором они lef join-ятся

И вообще как еще можно оптимизировать эти запросы?
zaartix:
и вообще есть средства какие-нибудь для замера скорости выполнения запроса? только не в виде 0.01 сек, а поточнее
Maus:
есть средства какие-нибудь для замера скорости
Можете покопаться в мане MySQL. Для медленных запросов там точно можно включить лог. Где-то также настраивается таймер, по истечении которого запрос считается медленным.
Дмитрий Котеров:
есть средства какие-нибудь для замера скорости выполнения запроса?
Сделайте EXPLAIN SELECT ... и посмотрите, в каком порядке MySQL собирается читать данные из таблиц, и какие индексы использовать. Прочитайте только предварительно документацию на EXPLAIN (там, если не ошибаюсь, и на русском есть). Это, правда, не совсем замер скорости, но - позволяет оптимизировать запросы.

Логирование запросов включается в my.cnf или командной строке mysql-сервера, см. документацию.
Юрий Насретдинов:
...В любом случае, запрос особо быстро исполняться не будет - серия более мелких запросов выполнится быстрее
Дмитрий Котеров:
серия более мелких запросов выполнится быстрее
Я в который раз говорю: это очень спорное утверждение, требующее фактического подтверждения. Мой опыт общения с MySQL говорит скорее об обратном: запрос с несколькими JOIN-ами ощутимо быстрее нескольких мелких запросов (но - тут, правда, тоже чисто субъективные ощущения). Кроме того, для других СУБД (FireBird, например) даже в документации написано, что несколько малких запросов хуже одного большого (из-за издержек сокетов). С MySQL, по идее, должно быть то же самое.
Юрий Насретдинов:
Дмитрий Котеров
Дим, надо поставить чистый эксперимент :). Если один большой запрос хорошенько оптимизировать, расставить везде нужные индексы, добиться видов связей только eq_ref, и т.д., то может и быстрее, но в любом случае грамотно сделанная серия (штуки 3-4) из мелких запросов будет работать по крайней мере не медленней одного большого.
Дмитрий Котеров:
Не понимаю я твоей логики. Ну почему же "не медленнее", когда
1. дополнительные издержки на сокеты или tcp/ip;
2. оптимизатор не использует статистическую информацию по индексам;
3. фаза парсинга запроса происходит не 1 раз, а 4.

Где выигрыш-то?
Maus:
Дмитрий Котеров, Юpий Насрeтдинов
Господа, давайте уточним, что обсуждается в этот раз:
Один большой запрос с JOIN-ами vs ...
1)... серии маленьких независимых запросов
2)... серии маленьких запросов, вложенных в один общий запрос

Потому как первое уже обсуждалось.
А во втором случае 1. дополнительные издержки на сокеты или tcp/ip; отпадает, верно?
Дмитрий Котеров:
Ну, лично я обсуждаю 1, потому как 2 не очень много где поддерживается пока.
Юрий Насретдинов:
Где выигрыш-то?
А выигрыш в том, что ты не пользуешься оптимизатором MySQL вообще, ты всю его «грязную работу» выполняешь сам, разбивая один большой запрос на несколько более мелких, и ты в большинстве случаев можешь лучше «расписать график работы» MySQL, чем это может сделать даже самый умный оптимизатор.
Педагог:
Офф-топ: Создатели и модераторы форума - не пора ли завести на форуме раздел "MySQL" или "Базы данных"?
Дмитрий Котеров:
всю его «грязную работу» выполняешь сам, разбивая один большой запрос на несколько более мелких, и ты в большинстве случаев можешь лучше «расписать график работы» MySQL
Вот не согласен с этим пунктом. Когда MySQL оптимизирует запрос, он учитывает статистические данные по индексам, задействованным в таблице. К примеру, если нужно сделать JOIN по 2 полям, причем по первому полю длина индекса (ну или размер таблицы) 10, а по второму - 10000, то ясно, что надо вначале выбирать по первому, а потом по второму. Если ситуация поменяется, то оптимизатор это учтет - а я не смогу, потому что жестко задаю порядок выборки. Можно и еще кучу примеров придумать, когда оптимизатор гораздо лучше справляется, чем человек; см. EXPLAIN!
Maus:
Дмитрий Котеров
зато для маленьких запросов работает внутреннее кэширование MySQL...
и если из трех подзапросов в кэш не попадет один, то это одни потери времени, а для JOIN - все перемножится по новой, разве нет?
Дмитрий Котеров:
Все верно. Однако большие запросы кэшируются в 4.1 ничуть не хуже маленьких, а скрипты обычно выдают очень однотипную серию запросов. Так что "раздробленное кэширование" для скриптов вряд ли играет большую роль.
Юрий Насретдинов:
Дмитрий Котеров
В любом случае, при составлении JOIN-запроса довольно часто нужно их очень тщательно продумывать, сидеть с PMA и EXPLAIN, смотреть на типы связей... При нескольких небольших запросах этого делать не нужно. Я не спорю, что в большинстве случаев действительно удобнее использовать JOIN, но грубо говоря, скажем, на этом форуме - при выполнении запроса MySQL приходится для каждого поста обращаться к таблице с юзверями, а если бы JOIN не использовался, все данные о юзверях были бы получены «в один проход»... Так что вопрос тут очень спорный...
Дмитрий Котеров: древовидная
все данные о юзверях были бы получены «в один проход»...
Странно ты рассуждаешь. Ну как же можно заранее узнать, данные о каких "юзерах" нужны?

Аргумент насчет продумывания JOIN-запросов принимаю. В смысле, чтобы составить 10 коротких запросов, нужна сильно меньшая квалификация, чем для составления одного большого, это да. Но при чем тут скорость выполнения - по прежнему неясно.

Кстати, типичный случай, когда JOIN сильно быстрее серии запросов, - извлечение древовидной структуры из базы (не nested sets, а обычной): http://forum.dklab.ru/php/heap/HierarchicalStructuresInADb.html
Юрий Насретдинов:
Кстати, типичный случай, когда JOIN сильно быстрее серии запросов, - извлечение древовидной структуры из базы
Да, вот насчёт этого согласен... Вообще очень интересный способ извлечения данных :))

Но при чем тут скорость выполнения - по прежнему неясно.
А притом, что базе тоже нужно намного меньше «думать», чтобы выполнить серию простых запросов, чем выполнить один сложный, но «умный». Грубо говоря, иногда «думать» ей приходится дольше, чем выполнить «не думая» серию простеньких запросов. В общем, от ситуации зависит...
Дмитрий Котеров:
Я ж говорю: основная задержка - не из-за "думания" базы, а из-за накладных расходов на сокеты.
Юрий Насретдинов:
Дмитрий Котеров
Это смотря какая база ;)

Эта тема на forum.dklab.ru