9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【MySQL】UNION と UNION ALL はどっちが処理速度速いの?

Last updated at Posted at 2022-12-20

はじめに

この記事は ミライトデザイン Advent Calendar 2022 の 20 日目の記事となっています。

先日はbucchさんの「ReactでGoogleMapの実装をしてみた」でした!

SQLクエリを作成していてテーブルを結合する際にUNION ALLを使う機会があったのですが、
UNIONっていうのもあるし、どっちがどのくらい処理速度速いんだろ?っと疑問に思ったので実際に処理速度を計測してみることにしました。

UNION と UNION ALL

どちらも、別々のSELECT文で取得したデータを縦に結合して一つのデータとすることができる構文です。
大きな違いは「重複するデータを排除するかしないか」です。

結合の際の注意点として以下は覚えておく必要があります。

  • カラムの数が同じであること
  • カラムの型が同じであること

今回の目的は「処理速度の比較」なので簡単に説明します。

UNIONについて

公式サイトを確認すると

UNION [ALL | DISTINCT]

とあります。
どうやらUNIONと記述するとデフォルトで、

UNION DISTINCT

になるようです。

実際にUNIONを試してみます。
使用するテーブル以下2つです。
image.png

「id=3, 4」のレコードの内容が重複している状態です。
image.png

ではUNIONを使って2つのテーブルを結合してみます。

SELECT id, name FROM test_a
UNION
SELECT id, name FROM test_b

取得結果は以下です。
image.png

「test_a」 と 「test_b」 とでの合計のデータ数は8件ですが、
重複していた2件が排除され6件となっています。
(塗りつぶしの部分)
image.png

UNION ALL

UNIONと違ってレコードの重複を排除しません。

使用するテーブルは「UNION」の時と同じです。
image.png

ではUNION ALLを使って2つのテーブルを結合してみます。

SELECT id, name FROM test_a
UNION ALL
SELECT id, name FROM test_b

取得結果は以下です。
image.png

UNIONと違い2つのテーブルで重複している2件が排除されず8件全て取得されました。
image.png

実際に速度を比較してみる

ただ、その前にどっちが速いかの予想をしておきます。
それは・・・
UNION ALL
です。

理由はUNIONは「重複を排除」する処理を行っていて、
UNION ALLは行っていないからです。
行う処理は少ない方が速いんじゃないかな、という考えです。

前提

  • 結合するテーブルは2つです。
    • ここの説明では仮に「テーブルA」,「テーブルB」としておきます。
  • 用意したカラムは「id(int型),name(varchar型)」の2カラムのみ
  • UNIONUNION ALLの比較をするために重複レコードが存在する必要があリますが、重複レコード数は全体の「20%」とし、Bテーブルに持たせます。
    (%はエイヤーで決めましたがこういうパターンは●%がいいよ、などありましたら教えていただけますと幸いです)
  • クエリの実行は5回ずつ行い、比較は平均値で行います。
  • MySQLのバージョンは「5.7.34」です。
    (テスト環境作成の都合上PHPMyAdminを使用しました)

【例】データ件数「10件」の場合に作成するテーブルイメージ
image.png
テーブルA,B共に件数は10件とし、テーブルBの件数の20%をテーブルAのデータと重複させます。
ここでは10件なので2件をテーブルAのデータと重複させます。

※実際のレコードは重複したレコードと重複しないレコードの順序はバラバラなことがほとんどかとは思いますが、今回は単純にUNIONUNION ALLを比較したいだけなので重複データは並んでいます。
そのため実際は今回の計測結果よりも時間がかかることが予想されます。

計測するレコードの件数

今回6パターンのデータ取得の処理速度を計測してみます。

  1. 100件(20件重複)
  2. 1,000件(200件重複)
  3. 10,000件(2,000件重複)
  4. 100,000件(20,000件重複)
  5. 1,000,000件(200,000件重複)
  6. ※1,000,000件(重複なし)

UNIONUNION ALLは重複排除の有無なので重複しているデータを主としてで計測していますが、1パターンだけ、テーブルA,Bに重複がないとどのくらい違うのか?気になったので計測してみます。

計測結果

image.png

数字だけだと見づらいので平均値を使って縦棒グラフにしてみます。
(1,000,000件は文字がグラフに入りきらないので漢字で表記しています)
UNION と UNION ALL の速度比較.png

結果を箇条書きで記載します。
・100件〜10,000件まではUNIONUNION ALLには差があまりない
・100,000件、1,000,000件同士のテーブル結合だと顕著に速度差が出る
UNIONよりUNION ALLの方が速い
・データ重複なしの場合でもUNIONよりUNION ALLの方が速い

データ件数が少ない場合はさほど差がありませんでしたが、
データ件数が多くなるとUNION ALLの方が処理速度が速いという予想通りの結果になりました。

データ重複がないパターンを計測する前は、
重複を排除しないUNION ALLの方が速いだろうけど、UNIONUNION ALLでそこまで差はでないんじゃないかと考えていましたが、
データ重複のパターンと同様の差が出る結果となりました。

結果を踏まえて

UNIONはデータが重複していようがいまいが「重複がないか」のチェックを行うので、
データ重複の有無はそこまで速度に関係がなさそうです。

今回データ重複がない場合において、UNION ALLの方が処理速度が速いという結果のため、
絶対にデータ重複がない、と知っている場合は、
UNIONUNION ALLであれば速度的に優位なUNION ALLを選ぶべきということになります。

ただし仕様的にデータ重複を排除する必要がある場合、
優先順位は「速度 < 仕様」であり、仕様的にUNIONを選択することが正しければ、
速度的にUNION ALLが優位でもUNIONを使うべきですね。

おわりに

実際にUNIONUNION ALLを使ったクエリの処理速度を計測してみて、
速度差を実感でき、状況に応じて使い分ける必要性があることを理解できたので良かったです。
今後、より効率の良いクエリ作成を心がけていきます!

さて、明日の記事はクエリマスターのNyokkiさんです。
クエリといえばNyokkiさん、Nyokkiさんといえばクエリ、非常に楽しみです。

参考

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?