UNION ALL MYSQL 真的很慢
UNION ALL MYSQL is really slow
我在 mysql 中有一个查询,来自 2 select 个。当我单独 运行 这些查询时,它们 运行 在 1 秒内很快。但是,当我将它们与 union all 结合使用时,网站冻结并且在 union all 中执行相同的查询至少需要 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
UNION 默认为 UNION DISTINCT。如果你想要 UNION ALL,明确地说(你应该尽可能,因为 UNION DISTINCT 必须做很多工作才能使它们不同)。
另一件事是,order by 和 limit 作为一个整体应用于查询。您可能想让每个联合查询也有它们。见 https://dev.mysql.com/doc/refman/8.0/en/union.html:
ORDER BY and LIMIT in Unions
To apply an ORDER BY or LIMIT clause to an individual SELECT, parenthesize the SELECT and place the clause inside the parentheses:
(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
合并之前,减小每个子查询返回的表的大小。由于只想要前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
我在 mysql 中有一个查询,来自 2 select 个。当我单独 运行 这些查询时,它们 运行 在 1 秒内很快。但是,当我将它们与 union all 结合使用时,网站冻结并且在 union all 中执行相同的查询至少需要 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
UNION 默认为 UNION DISTINCT。如果你想要 UNION ALL,明确地说(你应该尽可能,因为 UNION DISTINCT 必须做很多工作才能使它们不同)。
另一件事是,order by 和 limit 作为一个整体应用于查询。您可能想让每个联合查询也有它们。见 https://dev.mysql.com/doc/refman/8.0/en/union.html:
ORDER BY and LIMIT in Unions
To apply an ORDER BY or LIMIT clause to an individual SELECT, parenthesize the SELECT and place the clause inside the parentheses:
(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
合并之前,减小每个子查询返回的表的大小。由于只想要前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