繁体   English   中英

MySQL中UNION ALL的性能不佳

[英]Poor UNION ALL performance in MySQL

我有一个行如下的数据库:

+------------+---------+------------+-------+
| continent  | country | city       | value |
+------------+---------+------------+-------+
| Asia       | China   | Beijing    | 3     |
| ...        | ...     | ...        | ...   |
| N. America | USA     | D.C        | 7     |
| ....       | ....    | ....       | ....  |

为了生成树形图的可视化效果,我需要将其加工成具有以下形状的表:

+-----+------------+-------+
| uid | parent-uid | value |
+-----+------------+-------+

在这种情况下, AsiaChina的“父母”,而BeijingChina的“父母”。 因此,对于这三个你会碰到这样

+---------+--------+-----+
| Beijing | China  | 3   |
| China   | Asia   | ... |
| Asia    | global | ... |
+---------+--------+-----+

“价值”为China需要在所有子值的总和。 同样, Asia的价值必须是所有儿童价值的总和。

为了纯粹在SQL中完成此操作,我创建了以下三个查询,并将它们与UNION ALL结合在一起:

# City-level:
SELECT
     CONCAT(continent, "-", country, "-", city) as uid,
     CONCAT(continent, "-", country) as parentuid,
     value
FROM
     table

UNION ALL

# Country-level
SELECT
     CONCAT(continent, "-", country) as uid,
     continent as parentuid,
     SUM(value) as value
FROM
     table
GROUP BY
     country

UNION ALL

# Continent-level
SELECT
    continent as uid,
    "global" as parentuid,
    SUM(value) as value
FROM
    table
GROUP BY
    continent

每个单独的查询都以毫秒为单位完成。 市级,国家级和洲级的所有返回结果均在<0.01秒内

当我将它们结合在一起时,突然需要8秒才能获得结果!

我已经尝试使用Google搜索问题,但所有内容都只是说“使用UNION ALL而不是UNION ”(我已经是)

我认为它可能没有足够的RAM来构建临时结果表,所以这是磁盘浪费,但是我不知道如何增加内存限制。 我尝试将innodb_buffer_pool_size到1GB(1073741824),但没有帮助

第一个select ,选择表中的所有行然后让第一行是非常快的,但获取的所有行会采取很多的时间(MySQL的工作台追加limit 1000在默认情况下查询的结束)。

要测试获取所有行需要更多的时间,请尝试以下查询并向我们说它消耗的时间:

select * from (
SELECT
     CONCAT(continent, "-", country, "-", city) as uid,
     CONCAT(continent, "-", country) as parentuid,
     value
FROM
     table
) t1;

如果花费将近8秒钟,那么您的工会将没有问题。 为了提高性能,您必须使用where子句限制行。

希望对您有所帮助。

我想我的问题是: WITH ROLLUP什么问题?

SELECT
    CONCAT_WS('-',continent,country,city) as uid,
    CONCAT_WS('-',continent,COALESCE(country,'global')) as parentuid,
    value
FROM (
    SELECT continent, country, city, SUM(value) as value
    FROM table
    GROUP BY continent, country, city WITH ROLLUP
) t1
WHERE t1.continent IS NOT NULL;

我可能没有正确的CONCAT_WS()调用,尤其是当您有名为''城市或国家时,但我不得不认为这样做会更快。 WHERE子句仅用于删除总体摘要。

这是来自MySQL文档的WITH ROLLUP的示例,以帮助解释其功能:

mysql> SELECT year, country, product, SUM(profit)
    -> FROM sales
    -> GROUP BY year, country, product WITH ROLLUP;
+------+---------+------------+-------------+
| year | country | product    | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer   |        1500 |
| 2000 | Finland | Phone      |         100 |
| 2000 | Finland | NULL       |        1600 |
| 2000 | India   | Calculator |         150 |
| 2000 | India   | Computer   |        1200 |
| 2000 | India   | NULL       |        1350 |
| 2000 | USA     | Calculator |          75 |
| 2000 | USA     | Computer   |        1500 |
| 2000 | USA     | NULL       |        1575 |
| 2000 | NULL    | NULL       |        4525 |
| 2001 | Finland | Phone      |          10 |
| 2001 | Finland | NULL       |          10 |
| 2001 | USA     | Calculator |          50 |
| 2001 | USA     | Computer   |        2700 |
| 2001 | USA     | TV         |         250 |
| 2001 | USA     | NULL       |        3000 |
| 2001 | NULL    | NULL       |        3010 |
| NULL | NULL    | NULL       |        7535 |
+------+---------+------------+-------------+

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM