Предложение SQL IN медленнее, чем отдельные запросы - PullRequest
4 голосов
/ 20 марта 2009

Я использую реализацию JPA Hibernate с MySQL 5.0.67. MySQL настроен на использование InnoDB.

При выполнении запроса JPA (который переводится на SQL) я обнаружил, что использование предложения IN медленнее, чем выполнение отдельных запросов. Пример:

SELECT p FROM Person p WHERE p.name IN ('Joe', 'Jane', 'Bob', 'Alice')

медленнее, чем четыре отдельных запроса:

SELECT p FROM Person p WHERE p.name = 'Joe'
SELECT p FROM Person p WHERE p.name = 'Jane'
SELECT p FROM Person p WHERE p.name = 'Bob'
SELECT p FROM Person p WHERE p.name = 'Alice'

Почему это? Это ограничение производительности MySQL?

Ответы [ 6 ]

11 голосов
/ 20 марта 2009

Это известный недостаток MySQL.

Часто верно, что использование UNION работает лучше, чем запрос диапазона, подобный тому, который вы показываете. MySQL не очень разумно использует индексы для выражений, использующих IN (...). Аналогичная дыра существует в оптимизаторе для логических выражений с OR.

См. http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/ для некоторых объяснений и подробных ориентиров.

Оптимизатор постоянно совершенствуется. Недостаток в одной версии MySQL может быть исправлен в следующей версии. Поэтому стоит проверить ваши запросы в разных версиях.

Также выгодно использовать UNION ALL вместо простого UNION. Оба запроса используют временную таблицу для хранения результатов, но разница в том, что UNION применяет DISTINCT к набору результатов, что приводит к дополнительной неиндексированной сортировке.

1 голос
/ 20 марта 2009

Простой запрос, показанный в IN, не должен иметь проблем с оптимизатором, который выбирает использование индекса. Работа UNION, упомянутая Биллом, требуется только иногда, когда у вас есть более сложные запросы. Это может быть проблема со статистикой индекса.

Вы провели АНАЛИЗ на рассматриваемом столе?

Сколько строк в таблице и сколько соответствует предложению IN?

Что EXPLAIN говорит о рассматриваемых запросах?

1 голос
/ 20 марта 2009

Если вы используете оператор IN, это мало чем отличается от высказывания:

(p.name = 'Joe' OR p.name = 'Jane' OR p.name = 'Bob' OR p.name = 'Alice')

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

0 голосов
/ 24 марта 2013

вы можете сделать предложение in быстрее, если сначала получите значения, а затем вставите значения в предложение in вместо встраивания запроса sql в оператор sql

Вот пример использования в предложении

0 голосов
/ 20 марта 2009

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

Следующая методика используется почти в каждом приложении PHP / MySQL, которое я создаю.

Я довольно часто использую предложение IN с цифровыми клавишами:

, например

возьмите пять главных предметов, и все подтипы могут быть:

$master_arr = mysql_query(
 select * from master table where master_id in (1,7,9,10)
);

, то:

$subitem_arr = mysql_query(
   select * from subitems table where par_master_id in (1,7,9,10)
);

добавление подмассива к основным элементам:

foreach($subitem_arr AS $sv){
     $m_key = $sv['par_master_id'];
     $s_key = $sv['subitem_id'];
     $master_arr[$m_key]['subitem'][$s_key] = $sv;
}

Это делает две вещи: 1.) столы не все проводятся одновременно с объединением 2.) только два запроса mysql создают дерево данных

0 голосов
/ 20 марта 2009

Вы измеряете время настенных часов или время выполнения запроса? Я предполагаю, что фактическое время выполнения для каждого из четырех отдельных запросов может составлять в целом меньше, чем время выполнения запроса IN, но общее время настенных часов будет намного больше для четырех запросов.

Это поможет иметь индекс для столбца имени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...