2008-12-04 2 views
0

Мне нужен совет относительно производительности subselect в MySQL. По той причине, что я не могу изменить, я не могу использовать JOIN для создания фильтра quesry, я могу только добавить другое предложение AND в WHERE.MySQL подзаголовок вопрос производительности?

Что в себе свободу от:

select tasks.* 
from tasks 
where 
    some criteria 
    and task.project_id not in (select id from project where project.is_template = 1); 

по сравнению с:

select tasks.* 
from tasks, project 
where 
    some criteria 
    and task.project_id = project.id and project.is_template <> 1; 

Обратите внимание, что существует относительно небольшое число проектов whete is_template = 1, и может быть большое количество проектов, где is_template <> 1.

Есть ли другой способ добиться того же результата без подзапросов, если я ничего не могу изменить и фильтровать?

ответ

5

Я считаю, что второй более эффективен, так как требует только одного выбора, но, конечно, вы должны ОБЪЯСНИТЬ каждый запрос и проверить результаты.

EXPLAIN select tasks.* 
from tasks 
where 
    some criteria 
    and task.project_id not in (select id from project where project.is_template = 1); 

EXPLAIN select tasks.* 
from tasks, project 
where 
    some criteria 
    and task.project_id = project.id and project.is_template <> 1; 
+0

Спасибо за подсказку EXPLAIN. Кажется, что добавление индекса на project.is_template помогает. – Marko

1

Сколько разница существует между ними может в значительной степени от того, что «некоторые критерии» и какие возможности использовать индексы, которые она предоставляет зависит. Но учтите, что они не эквивалентны с точки зрения результатов, если есть задачи, у которых нет проектов. Второй эквивалентно следующему:

select tasks.* 
from tasks 
where 
    some criteria 
    and task.project_id in (select id from project where project.is_template <> 1); 
+0

«некоторые критерии» могут в значительной степени уменьшить количество возвращаемых записей. task.project_id требуется, поэтому эти 2 запроса эквивалентны. Я выбираю запрос «не в», поэтому subselect возвращает намного меньший набор записей, чем если бы я выбрал «in». – Marko

0

Я думаю, что первый может лучше масштабируются:

Когда вы объединения, внутренне MySQL делает вид временной таблицы, состоящей из двух таблиц, соединенных в соответствии с джойн условия указаны. Вы не даете условия соединения, поэтому он создаст временную таблицу со всеми задачами, перечисленными против всех проектов. Я достаточно уверен (но проверяю с помощью инструмента объяснения), что он делает это до применения каких-либо предложений.

Результат: если их 10, это будет 10 * 10 строк = 100. Вы можете видеть, как это становится большим по мере роста числа. Затем он применяет место для этой временной таблицы.

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

Но если масштабирование не вызывает беспокойства, я не думаю, что это действительно имеет значение.

+0

Никто не согласен со мной .... Я хочу обсудить. – benlumley

+0

Попробуйте просто объяснить, чтобы доказать свою неправоту. – ysth

0

Избегайте подзапросов, подобных чуме, в версиях MySQL < 6.0, и я сомневаюсь, что вы используете 6.0, учитывая, что он все еще находится в альфа-фазе разработки. AFAIK, оптимизатор MySQL вообще не обрабатывает подзапросы. Некоторая важная работа переделала оптимизатор для 6.0, а подзапросы теперь работают намного лучше, но эти изменения не перешли в серии 5.0 или 5.1.

+0

Вы торгуете широкой кистью. Можете ли вы сделать свой комментарий конкретным в этом случае?Трудно понять, как отсутствие оптимизации может привести к существенной разнице, если она не повторяет подзапрос для каждой строки задачи, и тестирование производительности должно быть в этом случае. – ysth

+0

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

Смежные вопросы