序文 バックエンド開発では、一度に大量のデータがロードされ、メモリやディスク IO のオーバーヘッドが過剰になることを防ぐために、ページング表示が必要になることがよくあります。このとき、MySQL の LIMIT キーワードが必要になります。しかし、LIMIT ページングですべてがうまくいくと思いますか? まだ若すぎて単純すぎます。データ量が多い場合、LIMIT が引き起こす可能性のある問題の 1 つは、ディープ ページングです。 場合 ここでは、電子商取引の注文詳細の表示を例にとります。新しいテーブルは次のようになります。 テーブル `cps_user_order_detail` を作成します ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主キー', `user_id` varchar(32) NOT NULL DEFAULT '' COMMENT 'ユーザーID', `order_id` bigint(20) デフォルト NULL コメント '注文ID', `sku_id` bigint(20) unsigned NOT NULL COMMENT '製品ID', `order_time` datetime DEFAULT NULL COMMENT '注文時間、形式 yyyy-MM-dd HH:mm:ss', 主キー (`id`)、 キー `idx_time_user` (`order_time`,`user_id`) BTREE の使用 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='ユーザー注文詳細'; 次に、120 万件のレコードを手動でテーブルに挿入します。 ここで、ユーザーの注文詳細を注文時間の逆順にページに表示するという要件があります。 テーブル構造は合理化されており、要件はシンプルです。そこで、すぐにコードを書き終えて、テスト用にオンラインに公開しました。当初はすべて正常に動作していましたが、注文量が増え続けるにつれて、システムは次第に遅くなり、いくつかの遅いクエリが時々報告されました。 この時点で、これは LIMIT オフセットの問題であると考えるべきです。そうです、SQL が十分に美しくないのではなく、MySQL 自体のメカニズムの問題なのです。 ここでは、次の図に示すように、それぞれ 100 と 100 万の位置オフセットからページングする 2 つの SQL ステートメントを例として取り上げます。時間差が非常に大きいことがわかります。これには、他のデータの計算や処理にかかる時間は含まれません。1 回の SQL クエリには 1 秒以上かかるため、ユーザーに提供される機能では許容できません (電子商取引では、インターフェイスの RT が 200 ミリ秒を超えないことが求められることがよくあります)。 ここでは、以下に示すように実行プランを見てみましょう。 ここではまず、実行プランの Extra 列の可能な値と意味を紹介します。
上の図を見ると、同じステートメントでも、オフセットが異なるだけで、実行プランに大きな違いが生じます (少し誇張して表現してもかまいません)。最初のステートメントでは、LIMIT 100,6type 列の値が range であり、これは範囲スキャンを示しています。ref よりもパフォーマンスが 1 レベル低くなりますが、インデックスを使用することも考慮されており、インデックス プッシュダウンも適用されます。つまり、WHERE 後の順序時にインデックスが削除および選択され、後続の ORDER BY も WHERE 条件がフィルタリングされるときに同期的に実行されるインデックス プッシュダウンに基づいて最適化されます (テーブルに戻らずに)。 最適化 原因が分析されたので、実際の開発で LIMIT ディープ ページングを最適化するにはどうすればよいでしょうか。ここで 2 つの解決策を紹介します。 SELECT * FROM cps_user_order_detail d WHERE d.id > #{maxId} AND d.order_time>'2020-8-5 00:00:00' ORDER BY d.order_time LIMIT 6; 上記のコードに示されているように、これもページ分割されていますが、maxId 制限があります。これは何を意味するのでしょうか。maxId は、前のページの最大の主キー ID です。したがって、この方法を使用する前提は次のとおりです。1) 主キーは自動増分である必要があり、UUID にすることはできません。また、基本的なページング パラメータ pageNo、pageSize を渡すだけでなく、フロント エンドは前の各ページの最大 ID も取得する必要があります。2) この方法はランダムなページ ジャンプをサポートしていません。つまり、ページを上下に移動することしかできません。次の図は、有名な電子商取引会社の実際のページを示しています。 2 つ目は、Elastic Search 検索エンジン (転置インデックスに基づく) を使用することです。実際、Taobao などの電子商取引企業は、基本的にすべての製品を ES 検索エンジンに入れています (このような膨大なデータを MySQL に入れるのは不可能であり、Redis に入れるのは現実的ではありません)。しかし、ES 検索エンジンを使用しても、ディープ ページングの問題が発生する可能性があります。その場合はどうすればよいでしょうか?答えはカーソルスクロールを通じてです。この点についてはここでは詳しく説明しません。興味のある方は調べてみてください。 まとめ このブログを書いたのは、以前開発中に実際にそれを経験し、Byte のインタビューで面接官とそれについて話し合ったからです。 LIMIT の制限と最適化について知っていると、面接でそのことを伝えることができればプラスになります。MySQL の最適化はインデックスの構築と SQL の調整だけだと言わないでください (実際、実際の開発では、これら 2 つの最適化ソリューションの効果は最小限です)。結局のところ、MySQL の最適化がそれほど素晴らしいのであれば、ミドルウェアはそれほど多くないはずです。 上記は、MySQL で数千万のデータを迅速にページ分割する方法の詳細です。MySQL の高速ページ分割の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
<<: Ubuntu 20.04 に GitLab をインストールして設定する方法
雑談はここまでにして、インターネット上で見つかる高性能な Yahoo ウェブサイトを構築するための数...
この機能を実装するにあたり、本家ブロガーさんから拝借した方法では色の切り替えが実現できず、長い間考え...
1. はじめに:ウェブページにフラッシュ コンテンツを正常に表示したい場合は、ページ上のフラッシュ ...
ssh は私が最も頻繁に使用する 2 つのコマンドライン ツールのうちの 1 つです (もう 1 つ...
varchar の保存ルール4.0 未満のバージョンでは、varchar(20) は 20 バイトを...
1. はじめに画像は多くのスペースを占め、画像の数が増えるほど管理が難しくなるため、シンプルなラベル...
目次マルチ環境構成とは何ですか? また、なぜそれが必要なのですか? .env ファイルはどこで設定さ...
tomcat の containerID を見つけて、tomacat ディレクトリに入ります。 [r...
Alibaba Cloud セキュリティグループの概要Alibaba Cloud Server セ...
検索ミラー docker 検索 rocketmq画像バージョンを表示他の画像を表示したい場合は、画像...
この記事では、テーブル内のデータを追加、削除、変更するためのvue要素の具体的なコードを参考までに共...
1. Docker Compose の使用方法は docker コマンドの使用方法と非常に似ています...
一時テーブルとメモリテーブルメモリ テーブルとは、メモリ エンジンを使用するテーブルを指します。テー...
Linux システムでは、環境変数は適用範囲に応じて、システムレベルの環境変数とユーザーレベルの環境...
Linux に nginx と複数の tomcat をインストールする方法はここでは紹介しません。不...