ホームページ データベース mysql チュートリアル MySQLでページングを最適化するサンプルコードの詳細説明

MySQLでページングを最適化するサンプルコードの詳細説明

Mar 09, 2017 am 11:21 AM

インタビューの質問、MySQL テーブルに大量のデータがある場合にページングを行う方法。 。 。 。当時はデータ量が多い場合にテーブルに分割できることだけは知っていましたが、テーブルを分割せずにどうすればいいのかわかりませんでした。 。 。 。悲しいことに、エージェントに要求したのは、ほんの数個のデータと、それを完全に保持するための単純な制限とオフセット (フェイス カバー) のみです。 。 。

多くのアプリケーションは、最新または最も人気のあるレコードのみを表示する傾向がありますが、古いレコードにもアクセスできるようにするには、ページング ナビゲーション バーが必要です。ただし、MySQL を介してページングをより適切に実装する方法は常に頭の痛い問題です。既製のソリューションはありませんが、データベースの基礎となるレイヤーを理解すると、ページ分割されたクエリを最適化するのに役立ちます。

パフォーマンスが低い、よく使用されるクエリを見てみましょう。

りー

このクエリには 0.00 秒かかります。では、このクエリの何が問題なのでしょうか?実際、このクエリ ステートメントとパラメータには問題はありません。これは、以下のテーブルの主キーを使用し、15 レコードのみを読み取るためです。

りー

本当の問題は、次のように、オフセット (ページング オフセット) が非常に大きい場合です。 レコードが 200 万行ある場合、上記のクエリには 0.22 秒かかります。EXPLAIN を通じて SQL 実行プランを表示すると、SQL が 100015 行を取得しましたが、最終的に必要なのは 15 行だけであることがわかります。ページング オフセットが大きいと使用されるデータが増加し、MySQL は最終的には使用されない大量のデータをメモリにロードします。ほとんどの Web サイト ユーザーがデータの最初の数ページにしかアクセスしないと仮定しても、ページ オフセットが大きい少数のリクエストがシステム全体に損害を与える可能性があります。 Facebook もこれを認識していますが、1 秒あたりにより多くのリクエストを処理するためにデータベースを最適化するのではなく、リクエストの応答時間の変動を減らすことに重点を置いています。

ページング リクエストの場合、レコードの総数という非常に重要な情報がもう 1 つあります。次のクエリを通じてレコードの合計数を簡単に取得できます。

りー

ただし、ストレージ エンジンとして InnoDB を使用する場合、上記の SQL には 9.28 秒かかります。間違った最適化は、SQL_CALC_FOUND_ROWS を使用することです。SQL_CALC_FOUND_ROWS は、ページング クエリ中に事前に条件を満たすレコードの数を準備し、select FOUND_ROWS() を実行するだけでレコードの合計数を取得します。ただし、ほとんどの場合、クエリ ステートメントが短くてもパフォーマンスが向上するわけではありません。残念ながら、このページング クエリ方法は多くの主流フレームワークで使用されています。このステートメントのクエリ パフォーマンスを見てみましょう。

りー

このステートメントには 20.02 秒かかり、前のステートメントの 2 倍の長さになります。ページングに SQL_CALC_FOUND_ROWS を使用するのは非常に悪い考えであることがわかりました。

最適化する方法を見てみましょう。この記事は 2 つの部分に分かれており、最初の部分ではレコードの総数を取得する方法が説明され、もう 1 つの部分では実際のレコードを取得する方法が説明されています。

行数を効率的に計算する

使用するエンジンが MyISAM の場合は、COUNT(*) を直接実行して行数を取得できます。同様に、ヒープ テーブルでは、行番号もテーブルのメタ情報に格納されます。ただし、エンジンが InnoDB の場合、InnoDB はテーブル内の特定の行数を保存しないため、状況はさらに複雑になります。

行数をキャッシュし、デーモン プロセスを通じて定期的に更新するか、一部のユーザー操作によってキャッシュが無効になった場合は、次のステートメントを実行します:

SELECT *
FROM city
ORDER BY id DESC
LIMIT 0, 15
ログイン後にコピー

レコードを取得

次に、この記事の最も重要な部分を入力し、ページネーションに表示するレコードを取得します。前述したように、オフセットが大きいとパフォーマンスに影響するため、クエリ ステートメントを書き直す必要があります。デモンストレーションのために、新しいテーブル「ニュース」を作成し、それを話題性順に並べ替え (最新リリースが一番上にあります)、高パフォーマンスのページングを実装します。簡単にするために、最新のニュース リリースの ID も最大であると仮定します。

りー

より効率的な方法は、ユーザーが最後に表示したニュース ID に基づく方法です。次のページをクエリするステートメントは次のとおりです。現在のページに表示されている最後の ID を渡す必要があります。

りー

前のページをクエリするステートメントは似ていますが、現在のページの最初の ID を渡す必要があることと、順序を逆にする必要がある点が異なります。

りー

上記のクエリ方法は、単純なページングに適しています。つまり、特定のページ ナビゲーションは表示されず、「前のページ」と「次のページ」のみが表示されます。たとえば、ブログのフッターには「前のページ」と「次のページ」が表示されます。 " ボタン。しかし、実際のページ ナビゲーションを実現することがまだ難しい場合は、別の方法を考えてみましょう。

りー

上記のステートメントにより、ページング ボタンごとにオフセットに対応する ID を計算できます。このアプローチには別の利点もあります。新しい記事が Web サイトに公開されていると仮定すると、すべての記事の位置が 1 つ後ろに移動するため、ユーザーが記事を公開するときにページを変更すると、記事が 2 回表示されることになります。各ボタンのオフセットIDを固定すればこの問題は解決します。 Mark Callaghan も同様のブログを公開しており、インデックスと 2 つの位置変数を組み合わせて使用​​していますが、基本的な考え方は同じです。

  如果表中的记录很少被删除、修改,还可以将记录对应的页码存储到表中,并在该列上创建合适的索引。采用这种方式,当新增一个记录的时候,需要执行下面的查询重新生成对应的页号。

SET p:= 0;
UPDATE news SET page=CEIL((p:= p + 1) / $perpage) ORDER BY id DESC;
ログイン後にコピー

  当然,也可以新增一个专用于分页的表,可以用个后台程序来维护。

UPDATE pagination T
JOIN (
   SELECT id, CEIL((p:= p + 1) / $perpage) page
   FROM news
   ORDER BY id
)C
ON C.id = T.id
SET T.page = C.page;
ログイン後にコピー

  现在想获取任意一页的元素就很简单了:

SELECT *
FROM news A
JOIN pagination B ON A.id=B.ID
WHERE page=$offset;
ログイン後にコピー

  还有另外一种与上种方法比较相似的方法来做分页,这种方式比较试用于数据集相对小,并且没有可用的索引的情况下—比如处理搜索结果时。在一个普通的服务器上执行下面的查询,当有2M条记录时,要耗费2sec左右。这种方式比较简单,创建一个用来存储所有Id的临时表即可(这也是最耗费性能的地方)。

CREATE TEMPORARY TABLE _tmp (KEY SORT(random))
SELECT id, FLOOR(RAND() * 0x8000000) random
FROM city;

ALTER TABLE _tmp ADD OFFSET INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, DROP INDEX SORT, ORDER BY random;
ログイン後にコピー

  接下来就可以向下面一样执行分页查询了。

SELECT *
FROM _tmp
WHERE OFFSET >= $offset
ORDER BY OFFSET
LIMIT $perpage;
ログイン後にコピー

  简单来说,对于分页的优化就是。。。避免数据量大时扫描过多的记录。


以上がMySQLでページングを最適化するサンプルコードの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

MySQL:初心者向けのデータ管理の容易さ MySQL:初心者向けのデータ管理の容易さ Apr 09, 2025 am 12:07 AM

MySQLは、インストールが簡単で、強力で管理しやすいため、初心者に適しています。 1.さまざまなオペレーティングシステムに適した、単純なインストールと構成。 2。データベースとテーブルの作成、挿入、クエリ、更新、削除などの基本操作をサポートします。 3.参加オペレーションやサブクエリなどの高度な機能を提供します。 4.インデックス、クエリの最適化、テーブルパーティション化により、パフォーマンスを改善できます。 5。データのセキュリティと一貫性を確保するために、バックアップ、リカバリ、セキュリティ対策をサポートします。

MySQL:簡単な学習のためのシンプルな概念 MySQL:簡単な学習のためのシンプルな概念 Apr 10, 2025 am 09:29 AM

MySQLは、オープンソースのリレーショナルデータベース管理システムです。 1)データベースとテーブルの作成:createdatabaseおよびcreateTableコマンドを使用します。 2)基本操作:挿入、更新、削除、選択。 3)高度な操作:参加、サブクエリ、トランザクション処理。 4)デバッグスキル:構文、データ型、およびアクセス許可を確認します。 5)最適化の提案:インデックスを使用し、選択*を避け、トランザクションを使用します。

phpmyadminを開く方法 phpmyadminを開く方法 Apr 10, 2025 pm 10:51 PM

次の手順でphpmyadminを開くことができます。1。ウェブサイトコントロールパネルにログインします。 2。phpmyadminアイコンを見つけてクリックします。 3。MySQL資格情報を入力します。 4.「ログイン」をクリックします。

Navicatプレミアムの作成方法 Navicatプレミアムの作成方法 Apr 09, 2025 am 07:09 AM

NAVICATプレミアムを使用してデータベースを作成します。データベースサーバーに接続し、接続パラメーターを入力します。サーバーを右クリックして、[データベースの作成]を選択します。新しいデータベースの名前と指定された文字セットと照合を入力します。新しいデータベースに接続し、オブジェクトブラウザにテーブルを作成します。テーブルを右クリックして、データを挿入してデータを挿入します。

MySQLおよびSQL:開発者にとって不可欠なスキル MySQLおよびSQL:開発者にとって不可欠なスキル Apr 10, 2025 am 09:30 AM

MySQLとSQLは、開発者にとって不可欠なスキルです。 1.MYSQLはオープンソースのリレーショナルデータベース管理システムであり、SQLはデータベースの管理と操作に使用される標準言語です。 2.MYSQLは、効率的なデータストレージと検索機能を介して複数のストレージエンジンをサポートし、SQLは簡単なステートメントを通じて複雑なデータ操作を完了します。 3.使用の例には、条件によるフィルタリングやソートなどの基本的なクエリと高度なクエリが含まれます。 4.一般的なエラーには、SQLステートメントをチェックして説明コマンドを使用することで最適化できる構文エラーとパフォーマンスの問題が含まれます。 5.パフォーマンス最適化手法には、インデックスの使用、フルテーブルスキャンの回避、参加操作の最適化、コードの読み取り可能性の向上が含まれます。

NavicatでMySQLへの新しい接続を作成する方法 NavicatでMySQLへの新しい接続を作成する方法 Apr 09, 2025 am 07:21 AM

手順に従って、NAVICATで新しいMySQL接続を作成できます。アプリケーションを開き、新しい接続(CTRL N)を選択します。接続タイプとして「mysql」を選択します。ホスト名/IPアドレス、ポート、ユーザー名、およびパスワードを入力します。 (オプション)Advanced Optionsを構成します。接続を保存して、接続名を入力します。

SQLが行を削除した後にデータを回復する方法 SQLが行を削除した後にデータを回復する方法 Apr 09, 2025 pm 12:21 PM

データベースから直接削除された行を直接回復することは、バックアップまたはトランザクションロールバックメカニズムがない限り、通常不可能です。キーポイント:トランザクションロールバック:トランザクションがデータの回復にコミットする前にロールバックを実行します。バックアップ:データベースの定期的なバックアップを使用して、データをすばやく復元できます。データベーススナップショット:データベースの読み取り専用コピーを作成し、データが誤って削除された後にデータを復元できます。削除ステートメントを使用して注意してください:誤って削除されないように条件を慎重に確認してください。 WHERE句を使用します:削除するデータを明示的に指定します。テスト環境を使用:削除操作を実行する前にテストします。

NAVICATでSQLを実行する方法 NAVICATでSQLを実行する方法 Apr 08, 2025 pm 11:42 PM

NAVICATでSQLを実行する手順:データベースに接続します。 SQLエディターウィンドウを作成します。 SQLクエリまたはスクリプトを書きます。 [実行]ボタンをクリックして、クエリまたはスクリプトを実行します。結果を表示します(クエリが実行された場合)。

See all articles