groupbyとdistinctを使用した場合のパフォーマンスの大きな違い


81

HSQLDB500000エントリを含むテーブルを使用してサーバーでいくつかのテストを実行しています。テーブルにはインデックスがありません。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すべての個別のビジネスキーとともに含まれているため、のパフォーマンスはDISTINCT3秒向上しましGROUP BYたが、約9秒かかりました。

ではMySQL両方のクエリと同じプリフォーム:

MySQL:500 000行-5 000個の個別のビジネスキー:両方のクエリ:0.5秒MySQL:500 000行-すべての個別のビジネスキー: SELECT DISTINCT ...-11秒 SELECT ... GROUP BY business_key-13秒

したがって、問題はにのみ関連していHSQLDBます。

なぜこんなに劇的な違いがあるのか​​、誰かが説明してくれたらとてもありがたいです。


2
の結果を表示し、EXPLAIN PLAN実行後にDISTINCTクエリを実行して、GROUP BYキャッシュによってタイミングが歪んでいないかどうかを確認してください...
Yahia 2011年

クエリごとに同じプランを取得すると、テーブルデータまたは結果のいずれかがキャッシュされたように聞こえます。
a'r 2011年

私はそれらを何度も実行したので、キャッシュは問題ではないと信じています。EXLAIN PLAN FOR出力を投稿しています。
マーティンディミトロフ2011年

私にはアイデアがありSELECT DISTINCT business_key FROM (SELECT business_key FROM memory WHERE concept <> 'case' or attrib <> 'status' or value <> 'closed')ますが、よくわかりません。試してみてください。これはGROUP BY、私のアイデアが正しければ、同じパフォーマンスを示すはずです。
ヤヒア2011年

@Yahia:まだ非常に遅い-94秒。MySQLで同じクエリを実行して、何が表示されるかを確認します
Martin Dimitrov 2011年

回答:


77

2つのクエリは同じ質問を表します。どうやらクエリオプティマイザは2つの異なる実行プランを選択します。私の推測では、distinctアプローチは次のように実行されます。

  • すべてのbusiness_key値を一時テーブルにコピーします
  • 一時テーブルを並べ替える
  • 一時テーブルをスキャンして、前のアイテムとは異なる各アイテムを返します

group by以下のように実行することができます。

  • テーブル全体をスキャンし、の各値をbusiness keyハッシュテーブルに保存します
  • ハッシュテーブルのキーを返します

最初の方法は、メモリ使用量を最適化します。一時テーブルの一部をスワップアウトする必要がある場合でも、十分に機能します。2番目の方法は速度を最適化しますが、異なるキーが多数ある場合は大量のメモリが必要になる可能性があります。

十分なメモリがあるか、いくつかの異なるキーがあるため、2番目の方法は最初の方法よりもパフォーマンスが優れています。2つの実行プラン間で10倍または100倍のパフォーマンスの違いが見られることは珍しいことではありません。


返信いただきありがとうございます。あなたの推測はEXPLAIN出力から明らかですか?どちらも私には同じように見えます。
マーティンディミトロフ2011年

私が見る限り、計画は結合を実行する方法を指定していません。なぜ結合が実行されるのかさえわかりません。Explainの出力を読むには、おそらくHSQLDBスペシャリストが必要です。
Andomar 2011年

答えが示すように、2番目の方法はより多くのメモリを使用し、ガベージコレクション(GC)に頻繁にヒットする可能性があります。JVMメモリ割り当てを増やす場合、2つのクエリ時間の間に大きな違いはないはずです。
fredt 2011年

表にすべての個別のキーを入力して、追加のテストを行いました(上記を参照)。結果があなたの主張を証明していると思いますか?どうもありがとう。
マーティンディミトロフ

2
SMEの専門家は、例を使用してこれを詳細に説明できますか...この問題は何度も発生しましたが、回避できないようです...修正方法は知っていますが、方法と理由を知りたいのですが
singhswat 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.