MySQL 最適化技術における Limit クエリの最適化分析

MySQL 最適化技術における Limit クエリの最適化分析

序文

実際のビジネスでは、ページングは​​一般的なビジネス要件です。次に、制限クエリを使用します。制限クエリを使用すると、データが比較的小さい場合や、データの最初の部分のみがクエリされる場合に効率が非常に高くなります。ただし、データ量が大きい場合や、クエリ オフセットの数が多い場合 (limit 100000,20 など) は、効率が不十分になることがよくあります。一般的な方法は、Limit を order by と組み合わせて使用​​することです。order by にユーザー用のインデックスがある場合、効率は通常かなり良好です。

この場合、最も単純なクエリは、カバーリング インデックスを使用して特定の必要な列をクエリすることです。この効果は非常に良いです

下記の通り

mysql> SELECT * FROM 学生 LIMIT 1000000,1;
+---------+-------------+-------------+----------+--------+----------------------+
| id | first_name | last_name | created_at | score | updated_at |
+---------+-------------+-------------+----------+--------+----------------------+
| 1000001 | kF9DxBgnUi | yLXnPSHJpH | 2019-07-11 | 97 | 2019-07-11 14:29:59 | |
+---------+-------------+-------------+----------+--------+----------------------+
セット内1列(0.31秒)

時間を見ることができます

mysql> EXPLAIN SELECT score,first_name FROM student ORDER BY created_at LIMIT 1000000,20 \G
************************** 1. 行 ****************************
   id: 1
 選択タイプ: シンプル
  テーブル: 学生
 パーティション: NULL
   タイプ: インデックス
可能なキー: NULL
   キー: time_source_name
  キーの長さ: 69
   参照: NULL
   行数: 1000001
  フィルター: 100.00
  追加: インデックスの使用
セットに 1 行、警告 1 件 (0.00 秒)

マイSQL>

この方法では、クエリ対象の列はカバーリング インデックスを使用し、スキャンされる行数は大幅に削減されますが、効果はあまり満足のいくものではありません。他のクエリがある場合、そのようなクエリは非常に遅くなります。

たとえば、last_name 列を追加します。

次のように

mysql> SELECT score,first_name,last_name FROM student ORDER BY created_at LIMIT 1000000,1;
+-------+------------+------------+
| スコア | 名 | 姓 |
+-------+------------+------------+
| 86 | knKsV2g2fY | WB5qJeLZuk |
+-------+------------+------------+
セット1列目(4.81秒)

マイSQL>

このクエリの実行には 4 秒強かかります。分析により、このクエリではインデックスを使用できないことがわかります。

mysql> explain SELECT score,first_name,last_name FROM student ORDER BY created_at LIMIT 1000000,1\G
************************** 1. 行 ****************************
   id: 1
 選択タイプ: シンプル
  テーブル: 学生
 パーティション: NULL
   タイプ: すべて
可能なキー: NULL
   キー: NULL
  キー長さ: NULL
   参照: NULL
   行数: 6489221
  フィルター: 100.00
  追加: filesort の使用
セットに 1 行、警告 1 件 (0.00 秒)

マイSQL>

ここでクエリを次のように変更します。

mysql> SELECT student.score,student.first_name FROM student INNER JOIN (SELECT id FROM student ORDER BY created_at LIMIT 1000000,1 ) AS temp USING(id);
+-------+-------------+
| スコア | 名 |
+-------+-------------+
| 15 | 2QWZ |
+-------+-------------+
セット内1列(0.18秒)
mysql> EXPLAIN SELECT student.score,student.first_name,last_name FROM student INNER JOIN (SELECT id FROM student ORDER BY created_at LIMIT 1000000,1) AS temp USING(id);
+----+--------------+-------------+------------+----------+---------------+-----------------+----------+-----------+-----------+-------------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+--------------+-------------+------------+----------+---------------+-----------------+----------+-----------+-----------+-------------+-------------+
| 1 | PRIMARY | <derived2> | NULL | ALL | NULL | NULL | NULL | NULL | 1000001 | 100.00 | NULL |
| 1 | プライマリ | 学生 | NULL | eq_ref | プライマリ | プライマリ | 4 | temp.id | 1 | 100.00 | NULL |
| 2 | 派生 | 学生 | NULL | インデックス | NULL | time_source_name | 69 | NULL | 1000001 | 100.00 | インデックスを使用 |
+----+--------------+-------------+------------+----------+---------------+-----------------+----------+-----------+-----------+-------------+-------------+
セットに 3 行、警告 1 件 (0.00 秒)

分析結果から、この時点でクエリされたデータ レコードは 1000001 件だけであることがわかります。なぜこのような変化が起きたのでしょうか?これは遅延結合と呼ばれます。最初にカバーインデックスクエリを使用して必要な主キーを返し、次に主キーに基づいて元のテーブルを結合して必要なデータを取得するため、スキャンする必要がある行数が可能な限り削減されます。

特定の状況では、実際には別の最適化ソリューションが存在します。たとえば、最近挿入されたレコードをいくつか取得します。次に、最後のクエリの最後のレコードの主キー ID (last_id) を記録できます。
クエリは次のように変更できる。

SELECT score,first_name,last_name,id FROM student WHERE id>=last_id ORDER BY id ASC LIMIT 1

たとえば、last_id=1000000 の場合、クエリは 1000000 から開始されます。このようなシナリオでは、データのオフセットに関係なく、パフォーマンスは非常に良好になります。

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。

以下もご興味があるかもしれません:
  • MySQL の制限クエリ文を最適化する 5 つの方法
  • MYSQL ページング制限速度の最適化方法が遅すぎる
  • MySQL 制限ページング最適化方法の共有
  • Mysqlの制限を最適化し、100万から1000万までの高速ページングの複合インデックスを参照し、軽量フレームワークに適用します。
  • MySQL クエリの最適化: LIMIT 1 はテーブル全体のスキャンを回避し、クエリの効率を向上させます
  • MySQL 制限オフセットの最適化の例
  • MySQL クエリの最適化: 結合クエリのソート制限の概要 (結合、順序、制限ステートメント)
  • PHP での MYSQL 制限の最適化
  • MySQL 制限クエリ最適化分析
  • Limitパラメータを使用してMySQLクエリを最適化する方法

<<:  Vue で 3D タグ クラウドを実装するための詳細なコード

>>:  Docker buildx を使用してマルチプラットフォーム イメージをビルドし、プライベート リポジトリにプッシュする方法

推薦する

フォームのmethod=post/getの違い

フォームは、get と post の 2 つのデータ転送方法を提供します。どちらもデータを送信する方...

MySQL マスター スレーブ データが矛盾しています。プロンプト: Slave_SQL_Running: 解決策はありません

この記事では、MySQL マスターとスレーブ データ間の不一致の解決方法と、プロンプト「Slave_...

FileZilla Server の FTP サーバー構成と 425 エラーおよび TLS 警告の解決策の詳細な説明

123WORDPRESS.COM では、FileZilla のダウンロード リンクを提供しています:...

MySQL パーティション フィールド列に別のインデックスを作成する必要がありますか?

序文パーティション フィールドは主キーの一部でなければならないことは誰もが知っています。では、複合主...

ジョセフリング問題を解決する 3 つの JavaScript メソッド

目次概要問題の説明循環リンクリスト順序付き配列数学的再帰要約する概要ジョセフ・リング問題は、ジョセフ...

WeChatアプレットはビデオプレーヤーのビデオコンポーネントを使用します

この記事の例では、WeChatアプレットのビデオプレーヤーコンポーネントの具体的なコードを参考までに...

CSS を使用して複数の方法で等高レイアウトを実装するサンプル コード

この記事で説明する等高レイアウトでは、純粋な CSS を使用して、要素の高さを手動で設定することなく...

SQL文のパフォーマンスを分析するための標準的な要約

この記事では、explain を使用して SQL ステートメントを分析する方法を紹介します。実際、イ...

Nginx proxy_redirect の使用方法の詳細な説明

今日、Apache の nginx リバース プロキシを実行していたときに、ちょっとした問題に遭遇し...

vue3+threejs を使用して iView 公式サイトのビッグウェーブ特殊効果の例を模倣する

目次序文1. レンダリング2. コード3. 背景画像素材要約する序文Threejs は、Web ベー...

Vue3 非同期データ読み込みコンポーネントサスペンスの使い方

目次序文コンポーネントの作成要約する序文Vue3 には多くの注目すべき機能が追加されましたが、サスペ...

HTML シンプルショッピング数量アプレット

この記事では、参考までにシンプルなHTMLショッピング数量アプレットを紹介します。具体的な内容は次の...

Amap を使用した React 実装例 (react-amap)

React の PC 版は Amap を使用するようにリファクタリングされました。情報を検索したと...

WeChatアプレットは写真の撮影とアルバムからの写真の選択を実現します

この記事では、WeChatアプレットで写真を撮ったり、アルバムから写真を選択したりするための具体的な...

JavaScript 開発における標準コミットメッセージの重要性の詳細な説明

目次標準コミットメッセージの重要性コミットするコミットリント依存関係をインストールする.commit...