У меня есть запрос в mysql с двумя вариантами выбора. Когда я запускаю эти запросы по отдельности, они выполняются быстро в течение 1 секунды. Но когда я объединяю их с объединением всех, веб-сайт зависает, и выполнение одного и того же запроса в объединении всех занимает не менее 20 секунд.
Любая идея, почему это происходит? Не могу понять.
См. запрос ниже:
SELECT p.user_id, p.description, p.post_id, p.created_at, ps.username AS size_name, ps.username AS user_name, ps.avatar AS avatar, pz.title AS title, pz.slug AS slug
FROM comments p
JOIN users ps ON ps.id = p.user_id
JOIN posts pz ON pz.id = p.post_id
UNION ALL
SELECT p2.user_id, p2.description, p2.post_id, p2.created_at, ps2.username AS size_name, ps2.username AS user_name, ps2.avatar AS avatar, pz2.title AS title, pz2.slug AS slug
FROM reply p2
JOIN users ps2 ON ps2.id = p2.user_id
JOIN posts pz2 ON pz2.id = p2.post_id
order by created_at DESC
LIMIT 10
@Barmar около 2 миллионов каждый.
Сначала выполните ORDER BY и LIMIT 10 в каждом SELECT. Затем сделайте это на СОЮЗЕ ВСЕХ результатов тоже.
Ваша проблема заключается в предложении ORDER BY. UNION должен получить все записи, а затем отсортировать их.
UNION по умолчанию имеет значение UNION DISTINCT. Если вы хотите использовать UNION ALL, прямо скажите это (и вы должны это делать везде, где это возможно, поскольку UNION DISTINCT должен проделать большую работу, чтобы сделать их разными).
Другое дело, что порядок и ограничение применяются к запросу в целом. Возможно, вы захотите, чтобы каждый объединенный запрос также имел их. См. https://dev.mysql.com/doc/refman/8.0/en/union.html:
ORDER BY и LIMIT в союзах
Чтобы применить предложение ORDER BY или LIMIT к отдельному SELECT, заключите SELECT в скобки и поместите предложение в круглые скобки:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
Если они были в ваших быстрых отдельных версиях, это должно помочь. Что-то вроде этого:
(SELECT p.user_id, p.description, p.post_id, p.created_at, ps.username AS size_name, ps.username AS user_name, ps.avatar AS avatar, pz.title AS title, pz.slug AS slug
FROM comments p
JOIN users ps ON ps.id = p.user_id
JOIN posts pz ON pz.id = p.post_id
order by created_at DESC
LIMIT 10)
UNION ALL
(SELECT p2.user_id, p2.description, p2.post_id, p2.created_at, ps2.username AS size_name, ps2.username AS user_name, ps2.avatar AS avatar, pz2.title AS title, pz2.slug AS slug
FROM reply p2
JOIN users ps2 ON ps2.id = p2.user_id
JOIN posts pz2 ON pz2.id = p2.post_id
order by created_at DESC
LIMIT 10)
order by created_at DESC
LIMIT 10
Я забыл добавить UNION ALL сюда, в stackoverflow. Я изменил это. Спасибо.
Этот запрос вернет всего 2 строки; 10 и 11.
Это вернет до 20 строк.
@Barmar, первый SELECT вернет до 10 строк, все значения 10. Второй SELECT вернет до 10 строк, все значения 11. UNION удалит дубликаты и вернет только один 10 и один 11 (если оба значения существуют.)
Это не соответствует исходному запросу, поскольку им нужны первые 10 строк из двух комбинированных запросов.
поскольку запрос из документации, похоже, смутил некоторых из вас, добавил один, настроенный на этот вопрос.
Перед слиянием с помощью UNION
уменьшите размер таблиц, возвращаемых каждым подзапросом. Поскольку вам нужны только первые 10, вам нужны только первые 10 каждого подзапроса.
SELECT *
FROM (
(SELECT p.user_id, p.description, p.post_id, p.created_at, ps.username AS size_name, ps.username AS user_name, ps.avatar AS avatar, pz.title AS title, pz.slug AS slug
FROM comments p
JOIN users ps ON ps.id = p.user_id
JOIN posts pz ON pz.id = p.post_id
ORDER BY created_at DESC
LIMIT 10)
UNION ALL
(
SELECT p2.user_id, p2.description, p2.post_id, p2.created_at, ps2.username AS size_name, ps2.username AS user_name, ps2.avatar AS avatar, pz2.title AS title, pz2.slug AS slug
FROM reply p2
JOIN users ps2 ON ps2.id = p2.user_id
JOIN posts pz2 ON pz2.id = p2.post_id
ORDER BY created_at DESC
LIMIT 10)
) AS x
order by created_at DESC
LIMIT 10
вы можете просто использовать круглые скобки, а не подзапрос, чтобы упорядочить/ограничить отдельные запросы; посмотри мой ответ
Но вам нужен внешний выбор, чтобы отфильтровать его до 10 лучших комбинированных запросов.
нет, не знаешь. вы можете заказать и ограничить отдельные запросы, а также заказать и ограничить союз в целом
о, не знал, что ты можешь сделать это так, как ты показываешь.
Сколько строк возвращает каждый из подзапросов?