Вопрос производительности при выборе MySQL?
-
19-08-2019 - |
Вопрос
Мне нужен совет относительно производительности выбора в MySQL.По причине, которую я не могу изменить, я не могу использовать JOIN для создания фильтра запросов, я могу только добавить еще одно предложение AND в WHERE.
В чем заключается эффективность:
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;
Обратите внимание, что существует относительно небольшое количество проектов с is_template = 1, и может быть большое количество проектов, где is_template <> 1.
Есть ли другой способ добиться того же результата без подвыборок, если я не могу ничего изменить, кроме фильтра и?
Решение
Я считаю, что второй более эффективен, так как требует только одного выбора, но чтобы быть уверенным, вы должны ОБЪЯСНИТЬ каждый запрос и проверить результаты.
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;
Другие советы
Разница между этими двумя показателями может сильно зависеть от того, что " некоторые критерии " есть и какие возможности использовать индексы он предоставляет. Но обратите внимание, что они не эквивалентны с точки зрения результатов, если есть задачи, у которых нет проектов. Второе эквивалентно этому:
select tasks.*
from tasks
where
some criteria
and task.project_id in (select id from project where project.is_template <> 1);
Я думаю, что первый может масштабироваться лучше:
Когда вы выполняете соединение, внутренне mysql создает своего рода временную таблицу, состоящую из двух таблиц, объединенных в соответствии с указанными условиями соединения. Вы не задаете условие соединения, поэтому оно создаст временную таблицу со всеми задачами, перечисленными для всех проектов. Я совершенно уверен (но проверяю с помощью инструмента объяснения), что он делает это до применения каких-либо предложений where. Р>
Результат: если их по 10, то будет 10 * 10 строк = 100. Вы можете увидеть, как это становится больше с ростом числа. Затем он применяет where к этой временной таблице.
Напротив, подзапрос выбирает только соответствующие строки из каждой таблицы.
Но если масштабирование не является проблемой, я не думаю, что это действительно имеет значение. Р>
Избегайте вложенных запросов, подобных чуме, в версиях MySQL < 6.0, и я сомневаюсь, что вы используете 6.0, учитывая, что он все еще находится в альфа-фазе разработки.AFAIK, оптимизатор MySQL вообще плохо обрабатывает подзапросы.Некоторая серьезная работа была проведена по обновлению оптимизатора для версии 6.0, и теперь вложенные запросы работают намного лучше, но эти изменения не коснулись серий 5.0 или 5.1.