序文 バックエンド開発では、一度に大量のデータがロードされ、メモリやディスク 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 をインストールして設定する方法
序文ドラッグ アンド ドロップ機能を追加すると、プログラムがより自然でユーザーフレンドリーになります...
Msyqlデータベースのインストール、参考までに具体的な内容は次のとおりです。 ①ブラウザでhttp...
目次Django でのタイムゾーン設定USE_TZ=真USE_TZ=偽Linux コンテナでのタイム...
本来、この第 7 章では、デザインにおけるレイヤーと空間テクニックについて深く議論するはずです。しか...
具体的なコードは次のとおりです。 <a href="#"> <...
この記事では、参考までにVue More Filter Itemウィジェットの実装方法を例として紹介...
VMware Toolsをインストールすると、仮想マシンホスト間で①テキストをコピーして貼り付けるこ...
まず、サーバーのハードウェアが現在のトラフィックをサポートするのに十分かどうかを確認します。通常の ...
CentOS7 64でのMySQL5.6.40のインストール手順1) 以前にインストールしたMySQ...
目次プロキシ転送ルール最初のもの: 2番目のタイプ: 3番目のタイプ: 4番目のタイプ: 5番目:プ...
目次1. 生放送効果2. ライブストリーミングを開始する手順2.1 Tencent Web(高速ライ...
以下のように表示されます。 test コマンドはファイルが存在するかどうかを判断します。 ssh u...
最近、データベース関連の操作が多くなり、会社の既存の仕様はあまり包括的ではありません。インターネット...
スタイル シートは、ドキュメントの表示方法、発音方法、または入力方法を記述します。XSL 言語は、X...
1. doctypeの役割、厳密モードと混合モードの違い、そしてその重要性1. 構文形式: <...