[MySQL] MySQL の分析 数百万のデータ深さのページング最適化アイデア

1. 事業背景

一般に、プロジェクト開発では、報告および分析する必要がある統計データが多数あります。一般に、分析後、ページで表示する操作や製品のバックグラウンドに表示されます。最も一般的なのは、日付でフィルターします。この種の統計データのサイズは時間の経過とともに徐々に増加し、数百万、数千万のデータに達するのは時間の問題です。

2. ボトルネックの再現

ユーザーテーブルを作成し、create_time フィールドにインデックスを追加しました。そしてテーブルに100wのデータを追加しました。
ここに画像の説明を挿入

ここでは、制限ページング方式を使用して、最初の 5 個のデータと最後の 5 個のデータの間のクエリ時間の差をクエリします。

最初の 10 項目のクエリには基本的に時間はかかりません
ここに画像の説明を挿入

50w+ からデータをフェッチすると、クエリに 1 秒かかります。
ここに画像の説明を挿入

キーワード SQL_NO_CACHE は、SQL クエリがキャッシュされないようにします。

同じ SQL ステートメント、異なるページング条件、および 2 つのパフォーマンスの差が非常に大きいため、データ量が増加するにつれて、後続のページのクエリに費やされる時間も論理的に増加します。

3. 問題分析

返品フォーム

通常、クエリ頻度が高いフィールドに対してインデックスを作成します。インデックスによりクエリの効率が向上します。上記のステートメントでは SELECT * FROM user を使用していますが、すべてのフィールドにインデックスが付けられているわけではありません。修飾されたデータをインデックス ファイルからクエリした後、インデックスが作成されていないフィールドをデータ ファイルからクエリすることも必要です。次に、このプロセスがテーブルにコールバックされます。

カバーインデックス

SELECT create_time FROM user など、クエリされたフィールドにインデックスが作成されている場合、クエリしたフィールドは作成したインデックスであるため、この時点でデータ ファイル内でクエリを実行する必要はなく、返す必要もありません。テーブルへ。この場合、それをカバリングインデックスと呼びます。

IO

テーブルの戻り操作は通常、 IO 操作です。これは、インデックスに従ってデータ行を見つけてから、クラスター化インデックスに移動して、データ行の主キーまたは一意のインデックスに従って特定のデータ行を見つける必要があるためです。クラスター化インデックスは通常、ディスクに保存されるデータ ファイルであるため、テーブルを返す操作を実行するときにディスクからデータを読み取る必要があり、ディスク IO は比較的遅い操作です。

リムティ2000,10 ?

LIMIT 2000, 10 が 1 ~ 2000 行をスキャンするかどうか考えたことはありますか? 以前に私と同じように、データは 2000 行から直接フェッチされ、前のデータはまったくスキャンされないか、データに返されないと考えたことはありませんか?テーブル。実際、この書き方では、完全なプロセスはデータをクエリすることですが、インデックスをカバーできない場合は、テーブルに戻ってデータをクエリする必要があります。

これで、後ろに行くにつれてクエリが遅くなる理由がわかりました。

4. 問題の概要

これで、後続のクエリが発生すると LIMIT のパフォーマンスが低下することがわかりました。パフォーマンスが低下する理由は、テーブルに戻る必要があるためです。問題が見つかったので、あとはクエリの回数を減らすだけです。テーブルに戻ってクエリのパフォーマンスを向上させます。

5. 解決策

カバーリングインデックスを使用するとデータがテーブルに戻らなくなる可能性があるため、まず主キー ID (主キーインデックス) を見つけて、見つかったデータを一時テーブルとして使用し、元のテーブルに JOIN することができます。処理する必要があるクエリ結果は 5 つだけです。 データはテーブルに返されるため、IO 操作が大幅に削減されます。

最適化前後のパフォーマンスの比較

実行効果を見てみましょう。

最適化前:1.4秒

ここに画像の説明を挿入

最適化後:0.2秒
ここに画像の説明を挿入

時間のかかるクエリのパフォーマンスが大幅に改善されました。このようにして、ページングされたデータが大きい場合でも、通常の制限クエリほど遅くはなりません。

おすすめ

転載: blog.csdn.net/u011397981/article/details/130719558