おはよう、
数百万行を含むテーブルがあり、タイムスタンプで並べ替えられたデータを表示する必要があります。
これをやろうとしたとき
SELECT * FROM table ORDER BY date DESC offset 0 LIMIT 200
MySQL はすべてのデータを並べ替えてから 200 行で応答しますが、これはパフォーマンスの問題です。ページをスクロールするたびにすべてを注文するのは賢明ではないからです。
パフォーマンスを改善する方法について何か考えはありますか?
おはよう、
数百万行を含むテーブルがあり、タイムスタンプで並べ替えられたデータを表示する必要があります。
これをやろうとしたとき
SELECT * FROM table ORDER BY date DESC offset 0 LIMIT 200
MySQL はすべてのデータを並べ替えてから 200 行で応答しますが、これはパフォーマンスの問題です。ページをスクロールするたびにすべてを注文するのは賢明ではないからです。
パフォーマンスを改善する方法について何か考えはありますか?
まず、日付フィールドに基づいてインデックスを作成する必要があります。これにより、リクエストが行われるたびにテーブル全体をソートしなくても、行を順番に取得できます。
次に、インデックスに基づくページングは、結果セットを深く掘り下げるほど遅くなります。説明する:
ORDER BY indexedcolumn LIMIT 0, 200
インデックスの 200 行をスキャンするだけでよいため、非常に高速です。
ORDER BY indexedcolumn LIMIT 200, 200
比較的高速ですが、400 行のインデックスをスキャンする必要があります。
ORDER BY indexedcolumn LIMIT 660000, 200
インデックスの 660,200 行をスキャンする必要があるため、非常に低速です。
注: それでも、インデックスをまったく持たない場合よりもはるかに高速になる可能性があります。
これはいくつかの方法で修正できます。
値ベースのページングを実装して、前のページの最後の結果の値に基づいてページングするようにします。例えば:
WHERE indexedcolumn>[lastval] ORDER BY indexedcolumn LIMIT 200
[lastval] を現在のページの最後の結果の値に置き換えます。インデックスにより、特定の値へのランダム アクセスが可能になり、その値から順方向または逆方向に進むことができます。
ユーザーに最初の X 行 (例: 1000 行) のみの表示を許可します。彼らが望む値が 2529 番目の値である場合、これは良くありません。
ユーザーが数百万行の結果セット全体に遭遇する必要がないように、たとえば最初の文字、年などで大きなテーブルを分割する論理的な方法を考えてください。代わりに、最初に特定のサブセットにドリルダウンする必要があります。これにより、セットが小さくなり、並べ替えが速くなります。
WHERE と ORDER BY を組み合わせている場合は、これをインデックスの設計に反映させて、MySQL がソート用のインデックスの恩恵を受け続けることができるようにする必要があります。たとえば、クエリが次の場合:
SELECT * FROM mytable WHERE year='2012' ORDER BY date LIMIT 0, 200
次に、インデックスを 2 つの列 (年、日付) にその順序で配置する必要があります。
クエリが次の場合:
SELECT * FROM mytable WHERE firstletter='P' ORDER BY date LIMIT 0, 200
次に、インデックスは 2 つの列 (firstletter、date) にその順序で配置する必要があります。
複数の列のインデックスを使用すると、前の列を条件で定数 (単一値) に指定している限り、任意の列で並べ替えることができます。したがって、WHERE 条件で A と B を定数として指定すると、A、B、C、D、および E のインデックスで C による並べ替えが可能になります。A と B を範囲にすることはできません。