“カウントがあるより速いものがありますか?大きなテーブルの場合?

StackOverflow https://stackoverflow.com/questions/818868

質問

ここに私のクエリがあります:

select word_id, count(sentence_id) 
from sentence_word 
group by word_id 
having count(sentence_id) > 100;

テーブルの「sentenceword」には、wordid、sentenceid、および主キーIDの3つのフィールドが含まれています。 350k行以上あります。 このクエリはなんと85秒かかりますが、100以上の文IDを持つすべての単語IDをすばやく見つける方法があるのではないかと思っています。

選択カウントの部分を取り出して、「have count(1)」を実行しようとしましたが、どちらも高速化しませんでした。

お役に立てれば幸いです。ありがとう!

役に立ちましたか?

解決

  

count(sentence_id)を持つ> 100;

これに問題があります...テーブルに重複した単語/文のペアがあるか、ありません。

単語/文のペアが重複している場合は、このコードを使用して正しい答えを取得する必要があります。

HAVING COUNT(DISTINCT Sentence_ID) > 100

テーブルに重複した単語/文のペアがない場合は、sentence_idをカウントせず、行をカウントするだけです。

HAVING COUNT(*) > 100

その場合、最適なパフォーマンスを得るために、 word_idのみ にインデックスを作成できます。

他のヒント

まだ持っていない場合は、sentence_id、word_idに複合インデックスを作成します。

クエリが頻繁に実行され、テーブルがめったに更新されない場合は、単語IDと対応する文数を含む補助テーブルを保持できます-それ以上の最適化を考えるのは困難です!

クエリは問題ありませんが、高速な結果を得るには少しのヘルプ(インデックス)が必要です。

手元にリソースがありません(またはSQLにアクセスできません)が、メモリからあなたを助けようとします。

概念的に、そのクエリに答える唯一の方法は、同じword_idを共有するすべてのレコードをカウントすることです。つまり、クエリエンジンには、これらのレコードをすばやく見つける方法が必要です。 word_idのインデックスがない場合、データベースでできることは、一度に1レコードずつテーブルを調べ、見つかったすべての個別のword_idの合計を実行し続けることだけです。通常、一時テーブルが必要になり、テーブル全体がスキャンされるまで結果をディスパッチできません。良くない。

word_idのインデックスを使用すると、まだテーブルを検索する必要があるため、あなたはあまり役に立たないと思います。ただし、SQLエンジンは、テーブルの最後まで待機することなく、各word_idのカウントを計算できるようになりました。( where 句を渡す場合は、その行のword_idの値とカウントをディスパッチできます) 、または行を破棄します(破棄しない場合)。その結果、サーバーのメモリ負荷が低くなり、部分的な応答になる可能性があります。また、一時テーブルは不要になります。 2番目の側面は並列処理です。 word_idのインデックスを使用すると、SQLはジョブをチャンクに分割し、個別のプロセッサコアを使用してクエリを並行して実行できます(ハードウェア機能と既存のワークロードに依存)。

これはクエリを支援するのに十分かもしれません。ただし、以下を確認する必要があります。

CREATE INDEX someindexname ON sentence_word (word_id)

(T-SQL構文。使用しているSQL製品を指定しなかった)

それでも十分でない場合(またはまったく役に立たない場合)、他に2つの解決策があります。

最初に、SQLでは、インデックス付きビューなどのメカニズムを使用して、COUNT(*)を事前計算できます。私は手元に詳細を持っていません(そして、私はこれを頻繁に行いません)。データが頻繁に変更されない場合、結果はより速くなりますが、複雑さと少しのストレージのコストがかかります。

また、クエリの結果を別のテーブルに保存することを検討することもできます。これは、データが変更されない場合、または正確なスケジュールで変更される場合(たとえば、午前2時にデータを更新する場合)、またはデータがほとんど変化せず、数時間完全でない結果で生活できる場合にのみ実用的です(定期的なデータ更新をスケジュールする必要があります);それは、貧乏人のデータウェアハウスに相当する道徳的なものです。

自分に合ったものを確実に見つける最良の方法は、上記のようないくつかの候補インデックスがある場合とない場合にクエリを実行し、クエリプランを調べることです。

驚くべきことに、大規模なデータセットでそれを実現するさらに速い方法があります:

SELECT totals.word_id, totals.num 
  FROM (SELECT word_id, COUNT(*) AS num FROM sentence_word GROUP BY word_id) AS totals
 WHERE num > 1000;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top