MySql ページングで limit+order by を使用する場合のデータ重複の解決策

MySql ページングで limit+order by を使用する場合のデータ重複の解決策

まとめ

複雑な知識をシンプルに説明できることは重要です

学習の過程で、私たちは多くの資料、ビデオ、文書などを読みました。現在では資料やビデオが非常に多いため、知識のポイントを説明するためにさまざまなビデオ形式が使用されることがよくあります。プロモーションマーケティング以外にも、動画による説明が優れている人はたくさんいます。例えば、李永楽先生の短い動画レッスンでは、複雑な知識を黒板で簡単かつ徹底的に説明できます。プログラミングを学んでいる私たちにとって、知識のポイントを明確に説明する方法だけでなく、それをわかりやすく書く方法も学ぶ必要があります。

問題の説明

MySQL では、通常、ページ クエリを実行するために limit を使用します。たとえば、limit(0,10) は最初のページに 10 個のデータをリストすることを意味し、limit(10,10) は 2 番目のページをリストすることを意味します。ただし、limit と order by が一致すると、2 ページ目に進んだときに最初のページのレコードが再び表示される場合があります。

詳細は以下の通りです。

選択
  `投稿タイトル`,
  `投稿日`
から
  役職
どこ
  `post_status` = '公開'
注文する
  表示回数の降順
制限
  5, 5

上記の SQL クエリを使用すると、LIMIT 0,5 と同一のレコードが表示される可能性が高くなります。以下の方法を使用すると重複は発生しません。

選択
  *
から
  役職
どこ
  post_status = '公開'
注文する
  表示回数の降順
制限
  5, 5

ただし、post テーブルには多くのフィールドがあるため、これら 2 つのフィールドのみを使用し、post_content もチェックしたくありません。この問題を解決するには、次のように、ORDER BY の後に 2 つの並べ替え条件を使用します。

選択
  `投稿タイトル`,
  `投稿日`
から
  役職
どこ
  `post_status` = '公開'
注文する
  表示回数の降順、
  ID昇順
制限
  5, 5

論理的に言えば、MySQL のソートでは、デフォルトで主キー ID がソート条件として使用されます。つまり、view_count が等しい場合、主キー ID がデフォルトのソート条件として使用され、ID asc を追加する必要はありません。しかし実際には、MySQL で order by と limit を混在させると、ソートが混乱します。

問題を分析する

MySQL 5.6 では、オプティマイザは order by limit ステートメントに遭遇すると、つまり、優先キューを使用して最適化を行います。

優先キューを使用する目的は、インデックス順序が使用できない場合に、ソートして制限 n を使用する必要があると、ソート処理中に n レコードのみを保持する必要があることです。これにより、すべてのレコードをソートするオーバーヘッドは解決できませんが、ソートを完了するためにソート バッファーに少量のメモリしか必要ありません。

MySQL 5.6 で 2 ページ目に重複データが存在する問題が発生する理由は、優先キューがヒープソート方式を採用しているためです。ヒープソート方式は不安定なソート方式です。つまり、同じ値のソート結果が、読み込んだデータの順序と一致しない可能性があります。

MySQL 5.5 にはこの最適化がないため、この問題は発生しません。

つまり、この記事で言及されている問題は MySQL 5.5 には存在せず、この状況はバージョン 5.6 以降でのみ発生しました。

MySQL が SQL 言語を解釈するときの実行順序を見てみましょう。

(1)選択
(2) DISTINCT <選択リスト>
(3)<left_table>から
(4) <結合タイプ> JOIN <右テーブル>
(5)ON <結合条件>
(6) WHERE <where_condition>
(7) GROUP BY <group_by_list>
(8) HAVING <having_condition>
(9) ORDER BY <order_by_condition>
(10) LIMIT <制限数>

実行順序は、form…where…select…order by…limit…となります。前述の優先キューにより、selectが完了した後、すべてのレコードがヒープソートで並べられます。order byを実行すると、view_count値が大きいレコードのみが前に移動します。

ただし、制限係数のため、ソート処理中に保持する必要があるレコードは 5 つだけです。view_count にはインデックス順序がないため、2 ページ目のデータを表示するときに、MySQL は表示されるレコードを取得します。したがって、ソート値が同じ場合、最初のソートはランダムになります。SQL を 2 回目に実行すると、結果は最初の結果と同じになります。

問題を解決する

(1)インデックスソートフィールド

フィールドにインデックスを追加すると、インデックスの順序に従って直接読み取り、ページ付けできるため、この問題を回避できます。

(2)ページングを正しく理解する

ページ区切りはソートに基づいており、数量の範囲に分割されています。ソートはデータベースによって提供される機能ですが、ページングは​​派生したアプリケーション要件です。

MySQL と Oracle の公式ドキュメントでは、limit n と rownum < n のメソッドが提供されていますが、ページングの概念は明確に定義されていません。

もう 1 つの重要な点は、上記のソリューションはユーザーにとってこの問題を軽減できますが、ユーザーの理解によっては、まだ問題があるということです。たとえば、このテーブルは頻繁に挿入され、ユーザーがクエリを実行すると、読み取りコミット分離レベルでは最初のページと 2 番目のページが依然として重複します。

したがって、ページングには常にこの問題があり、さまざまなシナリオではデータ ページングに非常に高い精度の要件はありません。

(3)データベースのソートに関するよくある問題

order by が追加されていない場合の並べ替えの問題

ユーザーが Oracle または MySQL を使用するとき、MySQL は常に整然としていますが、Oracle は非常に乱雑であることに気づきます。これは主に、Oracle がヒープ テーブルであり、MySQL がインデックス クラスター化テーブルであるためです。したがって、order by がない場合、データベースはレコードが返される順序を保証せず、各戻り値の一貫性も保証しません。

ページネーションの問題 ページネーションの重複の問題

前述のように、ページングは​​データベースが提供するソート機能から派生したアプリケーション要件であり、データベースはページングの重複を保証するものではありません。

NULL値と空文字列の問題

異なるデータベースでは、NULL 値と空の文字列の理解と処理が異なります。たとえば、Oracle の NULL と NULL 値を比較することはできません。それらは等しいわけでも等しくないわけでもなく、不明です。空の文字列を挿入すると、MySQL はそれを長さ 0 の空の文字列として扱いますが、Oracle は NULL 値を直接処理します。

これで、MySql ページングで limit+order by を使用するときにデータ重複問題を解決する方法に関するこの記事は終了です。MySql limit+order by ページングの詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQLサブクエリでorder byが効かない問題の解決方法
  • MySQLでorder byを使用せずにランキングを実装する3つの方法のまとめ
  • MySQLのorder byとlimitを混在させる際の落とし穴の詳細な説明
  • MySQL の group by と order by を一緒に使用する方法
  • インデックスを使用して MySQL ORDER BY ステートメントを最適化する方法
  • MySQL のソートとページング (order by と limit) と既存の落とし穴
  • MySQLにおける(JOIN/ORDER BY)文のクエリ処理と最適化方法
  • MySQLは「order by」がどのように機能するかを簡単に理解します
  • MySQL の order by ステートメントの最適化方法の詳細な説明
  • MySQL での order by の使用に関する詳細

<<:  CSS クロスフェード() を使用して半透明の背景画像効果を実現するサンプルコード

>>:  docker を使用してコード サーバーをデプロイする方法

推薦する

マインスイーパゲームを実装するための jQuery プラグイン (3)

この記事では、jQueryプラグインを使用してマインスイーパゲームを実装する方法に関する3番目の記事...

上部の固定ナビゲーションバーによって CSS アンカーの配置がブロックされる問題の解決方法

多くのウェブサイトでは、ユーザーが簡単に検索したり他のページに移動したりできるように、上部にナビゲー...

Vue3 AST パーサー - ソースコード分析

目次1. AST抽象構文木を生成する2. ASTのルートノードを作成する3. 子ノードの解析4. テ...

フォームから Vue ElementUI を使用してログイン効果を実装する例

目次1. ElementUIで基本的なスタイルを構築する2. [送信]ボタンをクリックして、アカウン...

2つのLinuxサーバー間でファイルとフォルダを転送する手順

今日、私はプロジェクトの移行の問題に取り組んでいましたが、突然、大量の写真をどうやって移動したらよい...

要素テーブルヘッダー行の高さの問題の解決

目次序文1. 問題の原因2. 解決策VueはelementUIテーブルtr thの高さと背景色を変更...

js の Array.forEach でループを終了する方法の例

目次forEach() メソッドjs の Array.forEach のループから抜け出す方法解決:...

HTMLはマーキーを使用してテキストを左右にスクロールします

コードをコピーコードは次のとおりです。 <本文> //マーキーの助けを借りて<MA...

Vueのref属性の詳細な説明

要約するこの記事はこれで終わりです。皆さんのお役に立てれば幸いです。また、123WORDPRESS....

ベスト HTML/CSS デザインおよび開発フレームワーク 15 選を紹介します

プロフェッショナルな Web デザインは複雑で時間がかかります。 HTML と CSS フレームワー...

Reactを使用して画像認識アプリを実装する方法

まずは効果の写真をお見せしましょう。 個人的には効果は問題ないと思います。アプリが写真を学習する時間...

JSはストップウォッチタイマーを実装します

この記事の例では、ストップウォッチタイマーを実装するためのJSの具体的なコードを参考までに共有してい...

Vueは物流タイムライン効果を実現します

この記事では、物流タイムライン効果を実現するためのVueの具体的なコードを例として紹介します。具体的...

ログインボックスのメールプロンプトを実装するネイティブJS

この記事では、登録またはログイン時に電子メール アドレスを入力する際のドロップダウン プロンプトのネ...

MySQL での正規表現置換のための replace と regexp の使用法の分析

この記事では、例を使用して、replace と regexp を使用して MySQL で正規表現を置...