4

次のようなクエリを最適化するのに苦労しています

SELECT RESULT_ID FROM RESULTS 
WHERE SOURCE = 1 AND GROUP=2 AND SCORE1 BETWEEN 20 AND 100 
ORDER BY SCORE2 LIMIT 450; 

4000万行のinnodbテーブル。上位 450 件を取得するには、クエリで最大 1,500 万件の結果を並べ替える必要がある場合があります。これまでのところ、次のことを試しました。

  1. インデックスを定義していますが、MySQL は範囲条件の後のインデックス内の列を無視するため、ソートに慣れていません。スコア列がたくさんあるので、いくつかの列で範囲条件を取得した後、特定のスコアで並べ替え、結果セットを上位 450 に制限することができます。
  2. メモリ テーブルを使用しますが、このような大きな結果を並べ替える場合はうまく機能しません。
  3. Sphinx ですが、この種のクエリに役立つかどうかはわかりません。

また、これらの種類のクエリを最適化できる OLAP キューブの実装はありますか?

4

3 に答える 3

1

一般的なスコア範囲を事前に指定できます。たとえば、いくつかのタイプの範囲を作成できます。

                1          2           3           4
RANGE_50  = { 0..50,    51..100,   101..150,   151..200 }
RANGE_100 = { 0..100,   101..200                        }
RANGE_200 = { 0..200                                    }

これらの範囲タイプはテーブルの列として作成でき、 score1の値に従って更新する必要があります。

次に、次のようなクエリを使用できるようになります。

SELECT RESULT_ID FROM RESULTS 
WHERE SOURCE = 1 AND GROUP=2 AND RANGE_100 = 2 
ORDER BY SCORE2 LIMIT 450; 
于 2011-08-12T00:03:00.070 に答える
1

あなたが探しているのは、私見ですが、(理論的には)無限のアイテムストリームで上位K個のアイテムを取得する方法です。

入力はストリームであり固定データセットではないため、これをmysqlで直接解決しようとはしません。また、データセットのサイズを考えると、すべての挿入で最初から上位の K を再計算することは問題外です。

私がすることは、新しいアイテムが入ってくるたびに更新する上位 K のコンパクトな表現を持つことです。各要素について、そのスコアを取得し、これまでに見た上位 K 要素のヒープを保持します。

もう少し形式的に: データ ストリーム q1, が与えられます。. . 、qn、Score(qj) がヒープ内の最小スコアよりも大きい場合、qj をヒープに追加します。この場合、最小の推定スコアをヒープから削除する必要があります。

具体的な解決策

複数のスコア列があり、ユーザーは範囲クエリを使用して列の任意の組み合わせを上位 450 に求めることができます。

概念的に、私がすることは次のとおりです。

  • 上記のストリーミング アプローチを使用して、スコア列ごとにトップ 450 をヒープに個別に保持する
  • クエリ時に、クエリに列ごとに一致するアイテムを取得します
  • 必要に応じてリストを集約およびソートし、450 でカットします

それが役に立てば幸い。

于 2011-08-11T22:39:51.967 に答える
1

これらの 450 行を保持し、新しい行が挿入されるか古い行が更新されるたびに計算され、他のテーブルを参照する別のテーブルを作成することをお勧めします。

そうすれば、クエリで毎回すべての行を参照する必要がなくなります。

于 2011-08-11T07:51:11.550 に答える