2

できるだけ早く実行する必要がある sqlite クエリがあります。クエリはかなり単純ですが、最大のパフォーマンスを得るためにテーブルにインデックスを付ける最良の方法がわかりません。

テーブルは「レキシコン」と呼ばれます。定義は次のとおりです。

_id integer primary key
word text
frequency integer
lset integer
rset integer

クエリは次のとおりです。

SELECT word,frequency FROM lexicon WHERE lset>? AND rset<? ORDER BY frequency DESC LIMIT ?

すべての個々の列にインデックスを付けましたが、複合インデックスの方が優れているのではないかと思いますが、どの組み合わせでしょうか? また、lset と rset のインデックスは昇順または降順である必要がありますか?

編集: lset と rset は、ツリー構造を表すネストされたセット値です。したがって、lset と rset のすべての値は相互に一意であり、完全に分散されています。また、任意の行で lset < rset.

前もって感謝します...

4

3 に答える 3

3

それはあなたのデータの統計に依存するでしょう。

とのすべての組み合わせlsetでインデックスを作成して、最良のケースを見つけることができますが、その場合、テーブルに実際のデータが必要です。 - ( , , ) - ( , , ) - ( , , ) - ( , , ) - ( , , ) - ( , , ) rsetfrequency
lsetrsetfrequency
rsetlsetfrequency
lsetfrequencyrset
rsetfrequencylset
frequencylsetrset
frequencyrsetlset

最初に持つ利点は、 and句frequencyに対して既に準備されていることです。ORDER BYLIMIT

しかし、レキシコン内のすべての単語の出現頻度が異なる場合、インデックスの 2 番目と 3 番目のフィールドは役に立たなくなります。 (データの統計が重要である理由の例。)

また、どのフィールドが最も速くレコードを制限するかも重要です。lset < xフィルターによってセットが元のサイズに縮小される場合は、0.01%そのフィルターをインデックスの最初に配置します。

しかし、おそらく、フィルター処理でlset < X and rset > y十分にインデックスを作成することは不可能です。

于 2012-05-22T16:04:10.813 に答える
2

この点で SQLite が他の DBMS と同じように動作する場合は、複合インデックスが必要になります...

{lset, rset DESC, frequency DESC}

...この特定の順序で、これらの特定のDESC句を使用します。

昇順/降順インデックスの詳細については、この記事をご覧ください。


はい、@DanielRenshaw が述べたようwordに、純粋にindex-only scanを許可するために、インデックスの最後に含めることができます。これは「カバリング」インデックスとして知られています。

(クラスタリング インデックスは既にすべてのフィールドをカバーしているため、そのようなインデックスに対してそれを行う目的はありません。)

于 2012-05-22T16:03:37.770 に答える
1

あなたのクエリ(名前にわずかな変更があります):

SELECT word,frequency 
FROM lexicon 
WHERE lset > @LeftSide 
  AND rset < @RightSide 
ORDER BY frequency DESC 
LIMIT @Num

Nested Set モデルを使用しているため、次のように書き換えることができます。

SELECT word,frequency 
FROM lexicon 
WHERE lset > @LeftSide          --- both `lset` here
  AND lset < @RightSide         --- and here
ORDER BY frequency DESC 
LIMIT @Num

両方の場合もありますrset。データがネストされたセット モデルに違反しない限り、どちらも機能し、同じ結果が得られます。したがって、クエリでは 3 つの列にカバリング インデックスが必要になる場合があります。

(lset, frequency, word)

インデックスを使用して、範囲に含まれる (場合によっては数千の) 行を識別し(@LeftSide,@RightSide)、ファイルソートを使用して、頻度の高い (@Num) 単語を見つけます。

場合によっては、インデックスをオンにした(frequency DESC, lset, word)方が良い場合があります (実際にはパラメーター値に依存します)。そのため、そのインデックスもあるとよいでしょう。しかし、SQLite がすべてのインスタンスで最高のインデックスを作成するかどうかについては、私には答えられません。

その範囲に入る行の数に応じて、パフォーマンスが良い場合とそうでない場合があります。しかし、この種のクエリをさらに最適化する簡単な方法はわかりません。

于 2012-05-22T17:42:40.597 に答える