2016-08-06 7 views
0

でALLパフォーマンス:悪いUNION私は、次のような行を持つデータベースを持っているMySQLの

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

ツリーマップの視覚化を生成するために、私は次のような形状を持つテーブルにこれを動作させる必要があります。

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

Asiaはの「親」であり、これはBeijingの「親」です。 Chinaための「値」は、すべての子値の集計である必要が

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

:だから、これらの3つのためにあなたのような何かを持っていると思います。同様に、Asiaの値はすべての子値の集合である必要があります。 SQLで純粋に、これを達成するために

私は、次の3つのクエリを作成し、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秒かかります!

私はそれがディスクトラッシングですので、それは一時的な結果テーブルを作成するための十分なRAMを持っていないかもしれないと考え

(私はすでに午前)私は問題をグーグルで試してみたが、すべてはただ「UNION ALL代わりのUNIONを使用してください」と言う

しかし、私はどのようにメモリの制限を増やすのか分からない。私は(1073741824)1ギガバイトにinnodb_buffer_pool_sizeをぶつけてみましたが、それは

+0

は、あなたはそれが結果セットの受け渡しやレンダリングをダウン物事を遅くしていませんクエリであることを確認していますか? –

+0

テーブルの行数はいくつですか?出力の行数 –

+0

どのくらいのRAMがありますか?どのバージョンのmysqlを使用していますか? (暗黙のテンポラリテーブルに問題がある可能性があります) –

答えて

1

最初selectを助けなかった、テーブル内のすべての行を選択し、その後、最初の行を取得することは非常に高速ですが、すべての行は、非常に多くの時間がかかりますフェッチ(MySQLのワークベンチ既定でクエリの末尾にlimit 1000を追加します)。

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

それはほとんど8秒かかる場合は、あなたの労働組合は何の問題もない:より多くの時間がかかるすべての行をフェッチすると、クエリ、次の試してみて、私たちにそれが消費時間を言うことをテストする

。また、パフォーマンスを向上させるには、where句を使用して行を制限する必要があります。

私はそれが助けてくれることを願っています。

+0

確かに、これはパフォーマンスを説明します。私が推奨した 'select * from(...)'クエリを使用したところ、0.0027秒から9.3秒になりました。 MySQLのワークベンチが私を混乱させていたと推測します。 – stevendesu

+0

@stevendesuうれしい、私は助けることができる –

1

私の質問は次のとおりです。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 | 
+------+---------+------------+-------------+ 
+0

'ロールアップは'私が必要なものを正確に行うことがあります(私はこれも事であることを知らなかった)。私は月曜日にそれを試し、何が起こるかを見てみましょう – stevendesu

+0

これをテストしたところ、私の 'UNION ALL'ソリューション(〜8秒ではなく〜11秒)よりも' WITH ROLLUP'を使って**ほんの少し長く**ました。私はそれが最も低いレベル(グループバイを使用していないとき)で、集計を選択するのではなく値を直接選択していたからだと思います。奇妙なことに、 'WITH ROLLUP'は275000行を返しましたが、私の' UNION ALL'ソリューションは250000行を返しました。私は、新しい列が何であるかは分かりません。オーストラリア(大陸/国は同じです)といくつかの奇妙なことがありますか? – stevendesu

関連する問題