Почему запросы UNION так медленны в MySQL?

Когда я оптимизирую свои 2 одиночных запроса, которые будут выполняться менее чем за 0,02 секунды, а затем UNION, результирующий запрос займет более 1 секунды. Кроме того, UNION ALL занимает больше времени, чем UNION DISTINCT. Я бы предположил, что разрешение дубликатов сделает запрос быстрее и не медленнее. Неужели мне просто лучше работать с двумя запросами отдельно? Я бы предпочел использовать UNION.

Ответ 1

Когда я оптимизирую свои 2 одиночных запроса для запуска менее чем за 0,02 секунды, а затем их UNION, результирующий запрос занимает более 1 секунды для запуска.

В ваши запросы входят предложения ORDER BY … LIMIT?

Если вы поместите ORDER BY … LIMIT после UNION, он будет применен ко всему UNION, и индексы в этом случае не могут быть использованы.

Если id является первичным ключом, этот запрос будет мгновенным:

SELECT  *
FROM    table
ORDER BY id
LIMIT 1

но этого не будет:

SELECT  *
FROM    table
UNION ALL
SELECT  *
FROM    table
ORDER BY id
LIMIT 1

Кроме того, a UNION ALL занимает больше времени, чем a UNION DISTINCT. Я бы предположил, что дублирование позволит сделать запрос быстрее и не медленнее.

Это также связано с ORDER BY. Сортировка меньшего набора быстрее, чем более крупная.

Неужели мне просто лучше работать с двумя запросами отдельно? Я бы предпочел использовать UNION

Вам нужен результирующий набор для сортировки?

Если нет, просто избавьтесь от окончательного ORDER BY.

Ответ 2

Догадка: Поскольку вы запрашиваете одну таблицу с двумя объединениями, возможно, что mysql испытывает трудности с выбором стратегии блокировки для таблицы или пытается кэшировать, что здесь не работает, поскольку вы запрашиваете непересекающиеся наборы, пытается многопоточно доступ (очень разумный), но работает с некоторыми проблемами блокировки/ concurrency/файлов.

В союзах

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

Эксперимент: Сделайте дубликат таблицы и соедините их. Если я прав, это должно быть быстрее.

Возможное решение: Разделите один файл на несколько файлов, чтобы обеспечить лучшие стратегии concurrency. Это не должно/не должно помочь в устранении проблем, но исключает проблемы многопоточности/поиска в базе данных.

Было бы полезно знать, какой механизм хранения вы используете.

Ну только мои 2 цента. Не могу проверить это здесь прямо сейчас.

Ответ 3

Может быть, вы измеряете время отклика, а не время для извлечения всех данных?