[解決済み] GROUP BYとDISTINCTを使用した場合のパフォーマンスの大きな違い
質問
私はあるテストを
HSQLDB
サーバーで、500 000 エントリを含むテーブルを使用していくつかのテストを実行しています。このテーブルにはインデックスがありません。5000の異なるビジネスキーがあります。私はそれらのリストが必要です。
当然ながら、私はまず
DISTINCT
クエリで開始します。
SELECT DISTINCT business_key
FROM memory
WHERE concept <> 'case' OR
attrib <> 'status' OR
value <> 'closed';
90秒くらいかかる!!!
そこで、試しに
GROUP BY
:
SELECT business_key
FROM memory
WHERE concept <> 'case' OR
attrib <> 'status' OR
value <> 'closed';
GROUP BY business_key
しかも1秒で終わる!!!
この違いを理解するために、私は
EXLAIN PLAN FOR
を実行しましたが、どちらのクエリも同じ情報を与えているようです。
EXLAIN PLAN FOR DISTINCT ...
isAggregated=[false]
columns=[
COLUMN: PUBLIC.MEMORY.BUSINESS_KEY
]
[range variable 1
join type=INNER
table=MEMORY
alias=M
access=FULL SCAN
condition = [ index=SYS_IDX_SYS_PK_10057_10058
other condition=[
OR arg_left=[
OR arg_left=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.CONCEPT] arg_right=[
VALUE = case, TYPE = CHARACTER]] arg_right=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.ATTRIB] arg_right=[
VALUE = status, TYPE = CHARACTER]]] arg_right=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.VALUE] arg_right=[
VALUE = closed, TYPE = CHARACTER]]]
]
]]
PARAMETERS=[]
SUBQUERIES[]
Object References
PUBLIC.MEMORY
PUBLIC.MEMORY.CONCEPT
PUBLIC.MEMORY.ATTRIB
PUBLIC.MEMORY.VALUE
PUBLIC.MEMORY.BUSINESS_KEY
Read Locks
PUBLIC.MEMORY
WriteLocks
EXLAIN PLAN FOR SELECT ... GROUP BY ...
isDistinctSelect=[false]
isGrouped=[true]
isAggregated=[false]
columns=[
COLUMN: PUBLIC.MEMORY.BUSINESS_KEY
]
[range variable 1
join type=INNER
table=MEMORY
alias=M
access=FULL SCAN
condition = [ index=SYS_IDX_SYS_PK_10057_10058
other condition=[
OR arg_left=[
OR arg_left=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.CONCEPT] arg_right=[
VALUE = case, TYPE = CHARACTER]] arg_right=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.ATTRIB] arg_right=[
VALUE = status, TYPE = CHARACTER]]] arg_right=[
NOT_EQUAL arg_left=[
COLUMN: PUBLIC.MEMORY.VALUE] arg_right=[
VALUE = closed, TYPE = CHARACTER]]]
]
]]
groupColumns=[
COLUMN: PUBLIC.MEMORY.BUSINESS_KEY]
PARAMETERS=[]
SUBQUERIES[]
Object References
PUBLIC.MEMORY
PUBLIC.MEMORY.CONCEPT
PUBLIC.MEMORY.ATTRIB
PUBLIC.MEMORY.VALUE
PUBLIC.MEMORY.BUSINESS_KEY
Read Locks
PUBLIC.MEMORY
WriteLocks
編集
追加でテストしてみました。500 000レコードで
HSQLDB
にある 500,000 件のレコードと、すべての明確なビジネス キーを使用した場合
DISTINCT
のパフォーマンスは 3 秒と向上しています。
GROUP BY
が約9秒かかっていたのに対して、3秒です。
で
MySQL
では、どちらのクエリも同じように実行されます。
MySQLを使用します。500 000 行 - 5 000 個のビジネス キー。
両方のクエリ 0.5秒
MySQLの場合 500 000行 - すべての異なるビジネス・キー。
SELECT DISTINCT ...
- 11秒
SELECT ... GROUP BY business_key
- 13秒
つまり、この問題は
HSQLDB
.
なぜこのような劇的な違いがあるのか、どなたか説明していただけると大変ありがたいのですが。
どのように解決するのですか?
2つのクエリは同じ質問を表現しています。 どうやら、クエリオプティマイザは 2 つの異なる実行計画を選択するようです。 私の推測では
distinct
のようなアプローチが実行されます。
-
すべてコピー
business_key
の値をテンポラリテーブルにコピーします。 - テンポラリテーブルをソートする
- テンポラリテーブルをスキャンし、前の項目と異なる各項目を返す
は
group by
のように実行することができる。
-
テーブル全体をスキャンし、それぞれの値を
business key
の各値をハッシュテーブルに格納します。 - ハッシュテーブルのキーを返す
最初の方法はメモリ使用量を最適化します。一時テーブルの一部をスワップアウトしなければならない場合でも、それなりにうまく動作するでしょう。 2番目の方法は速度を最適化しますが、多くの異なるキーがある場合、大量のメモリを必要とする可能性があります。
十分なメモリがあるか、異なるキーがほとんどないため、2 番目の方法は 1 番目の方法よりも性能が高くなります。 2 つの実行プランの間に 10 倍、あるいは 100 倍の性能差が生じることは珍しくありません。
関連
-
[解決済み] 複数の列でgroup byを使用する
-
[解決済み] 最初の行への結合方法
-
[解決済み] MySQLでFULL OUTER JOINを行うにはどうすればよいですか?
-
[解決済み] pandas GroupByを使ってグループごとの統計情報(カウント、平均値など)を取得する?
-
[解決済み] mysqldumpで特定のテーブルをスキップする
-
[解決済み] 項目xにアクセスできるように文字列を分割するにはどうすればよいですか?
-
[解決済み] C言語のi++と++iに性能差はあるのでしょうか?
-
[解決済み] Entity Framework VS LINQ to SQL VS ADO.NETでストアドプロシージャを使う?[クローズド]
-
[解決済み] GROUP BYとDISTINCTの違いは何ですか?
-
[解決済み】MySQLでSELECT DISTINCTとGROUP BYのどちらが速いか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] SQLの結合形式 - 入れ子になった内側join
-
[解決済み] SQL Server の DateTime データ型から日付だけを返す方法
-
[解決済み] ...値に挿入する ( SELECT ... FROM ... )
-
[解決済み] UNIONとUNION ALLの違いは何ですか?
-
[解決済み] SQL Serverで、指定したテーブルを参照しているすべての外部キーを一覧表示するにはどうすればよいですか?
-
[解決済み] SQLの複数列の順序付け
-
[解決済み] SQL ServerにおけるINSERT OR UPDATEに関する解決策
-
[解決済み] SQLサーバーで行を列に効率的に変換する
-
[解決済み] 別のテーブルに一致する項目がない行を選択するにはどうすればよいですか?
-
[解決済み] has_many through リレーションシップからユニークなレコードを表示するには?