0

私は次のクエリを持っています:

select 
    t.Chunk as LeftChunk,
    t.ChunkHash as LeftChunkHash,
    q.Chunk as RightChunk,
    q.ChunkHash as RightChunkHash,
    count(t.ChunkHash) as ChunkCount
from
    chunks as t
    join
    chunks as q
    on
        t.ID = q.ID
group by LeftChunkHash, RightChunkHash

そして、次の説明表:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  t   ALL IDIndex NULL    NULL    NULL    17796190    "Using temporary; Using filesort"
1   SIMPLE  q   ref IDIndex IDIndex 4   sotero.t.Id 12  

「一時的な使用;ファイルソートの使用」に注意してください。

このクエリを実行すると、RAM(おそらく一時テーブルのb / c)がすぐに不足し、HDDが起動し、クエリが遅くなり停止します。

インデックスの問題かもしれないと思ったので、そのような意味のあるものをいくつか追加し始めました。

Table   Non_unique  Key_name    Seq_in_index    Column_name Collation   Cardinality Sub_part    Packed  Null    Index_type  Comment Index_comment
chunks  0   PRIMARY 1   ChunkId A   17796190    NULL    NULL        BTREE       
chunks  1   ChunkHashIndex  1   ChunkHash   A   243783  NULL    NULL        BTREE       
chunks  1   IDIndex 1   Id  A   1483015 NULL    NULL        BTREE       
chunks  1   ChunkIndex  1   Chunk   A   243783  NULL    NULL        BTREE       
chunks  1   ChunkTypeIndex  1   ChunkType   A   2   NULL    NULL        BTREE       
chunks  1   chunkHashByChunkIDIndex 1   ChunkHash   A   243783  NULL    NULL        BTREE       
chunks  1   chunkHashByChunkIDIndex 2   ChunkId A   17796190    NULL    NULL        BTREE       
chunks  1   chunkHashByChunkTypeIndex   1   ChunkHash   A   243783  NULL    NULL        BTREE       
chunks  1   chunkHashByChunkTypeIndex   2   ChunkType   A   261708  NULL    NULL        BTREE       
chunks  1   chunkHashByIDIndex  1   ChunkHash   A   243783  NULL    NULL        BTREE       
chunks  1   chunkHashByIDIndex  2   Id  A   17796190    NULL    NULL        BTREE       

しかし、まだ一時テーブルを使用しています。

dbエンジンはMyISAMです。

一時的な使用を取り除くにはどうすればよいですか。このクエリでfilesortを使用していますか?

根本的な原因を説明せずにInnoDBに変更するだけでは、特に満足のいく答えではありません。さらに、解決策が適切なインデックスを追加することである場合、それは別のデータベースエンジンに移行するよりもはるかに簡単です。

リレーショナルデータベースは初めてです。ですから、私はその解決策が専門家にとって明白なものであることを望んでいます。

編集1:

IDは主キーではありません。ChunkIDはです。IDごとに約40のChunkIDがあります。したがって、テーブルにIDを追加すると、約40行が追加されます。各一意のチャンクには、一意のchunkHashが関連付けられています。

EDIT2:

スキーマは次のとおりです。

Field   Type    Null    Key Default Extra
ChunkId int(11) NO  PRI NULL    
ChunkHash   int(11) NO  MUL NULL    
Id  int(11) NO  MUL NULL    
Chunk   varchar(255)    NO  MUL NULL    
ChunkType   varchar(255)    NO  MUL NULL    

編集3:

クエリの最終目的は、ドキュメント間での単語の共起のテーブルを作成することです。ChunkIDは単語インスタンスです。各インスタンスは、特定のドキュメント(ID)に関連付けられている単語です。ドキュメントごとに約40語が存在します。約100万のドキュメント。したがって、結果として得られる共起のテーブルは、(明らかに)作成されている完全な外積一時テーブルと比較して高度に圧縮されています。つまり、完全な外積一時テーブルは1 mil * 40 * 40=16億行です。圧縮された結果のテーブルは、約4,000万行と推定されます。

編集4:

postgresqlタグを追加して、postgresqlユーザーがそのSQL実装でより良い実行プランを取得できるかどうかを確認します。その場合は、切り替えます。

4

3 に答える 3

2

同じ結果を生成するクエリで更新されました。ただし、これ以上速くなることはありません。

Create Index IX_ID On Chunks (ID);

Select
  LeftChunk,
  LeftChunkHash,
  RightChunk,
  RightChunkHash,
  Sum(ChunkCount)
From (
  Select 
    t.Chunk as LeftChunk,
    t.ChunkHash as LeftChunkHash,
    q.Chunk as RightChunk,
    q.ChunkHash as RightChunkHash,
    count(t.ChunkHash) as ChunkCount
  From
    chunks as t
      inner join
    chunks as q
      on t.ID = q.ID
  Group By
    t.ID,
    t.ChunkHash,
    q.ChunkHash 
  ) x
Group By
  LeftChunk,
  LeftChunkHash,
  RightChunk,
  RightChunkHash

テストデータの例をいじる http://sqlfiddle.com/#!3/ea1a5/2

最新のフィドル、問題は言葉と文書として再定式化されています:http ://sqlfiddle.com/#!3/f5aef/12

問題が文書と単語として再定式化されたので、あなたはいくつの文書、いくつの単語、そしていくつの文書単語を持っていますか?

また、ドキュメントと単語のアナロジーを使用すると、クエリは「ドキュメントに一緒に表示される単語のすべてのペアについて、どのドキュメントでも一緒に表示される頻度です。単語Aがドキュメントに表示さnれ、単語Bが表示されるm場合同じドキュメントで、これはn * m合計の回数としてカウントされます。」

于 2012-11-16T00:16:43.597 に答える
2

結合する前にテーブルを要約するのはどうですか?

要約は次のようになります。

 select count(*) count,
        Chunk,
        ChunkHash
   from chunks
  group by Chunk, ChunkHash

次に、結合は次のようになります。

Select r.Chunk as RightChunk,
       r.ChunkHash as RightChunkHash,
       l.Chunk as LeftChunk,
       l.ChunkHash as LeftChunkHash
       sum (l.Count) + sum(r.Count) as Count
  from (
        select count(*) count,
               Chunk,
               ChunkHash
          from chunks
      group by Chunk, ChunkHash
       ) l
  join (
        select count(*) count,
               Chunk,
               ChunkHash
          from chunks
      group by Chunk, ChunkHash
       ) r on l.Chunk = r.Chunk
 group by r.Chunk, r.ChunkHash, l.Chunk, l.ChunkHash

私がよくわからないのは、正確に何を数えているのかということです。したがって、私のSUM()+ SUM()は推測です。SUM()* SUM()が必要な場合があります。

また、ChunkHash値が等しい場合に限り、2つのチャンク値が等しいと想定しています。

于 2012-11-16T00:20:27.753 に答える
2

MySQLからPostgreSQLに移行したところ、クエリの実行時間は約1。5日から約10分になりました。

PostgreSQLクエリ実行プランは次のとおりです。

ここに画像の説明を入力してください

私はもうMySQLを使用していません。

于 2012-12-03T22:50:13.143 に答える