MySQLの制限ページングクエリのパフォーマンスの最適化
MySQLのクエリページングは非常に簡単ですが、それは一般的なページングを大量のデータを着ているときとき。
伝統的なページングクエリ:SELECT C1、C2、... CNテーブルLIMITからのN、M
MySQLは読書の前で最初のnレコードの動作原理を制限して、最初のnを破棄することであり、mが読み込まれた後に、そのnは、大きなオフセット、より悪いパフォーマンスをしたいです。
推奨ページングクエリ方法:
図1は、可能な限りクエリのおおよその範囲を与えられます
- SELECT C1 、C2 、CN ... テーブルFROM WHERE ID > = 20000 LIMIT 10 。
図2に示すように、サブクエリメソッド
- SELECT C1 、C2 、CN ... FROMテーブルWHERE ID > =
- (
- 表LIMIT FROM SELECT ID 20000 、1
- )
- LIMIT 10 ;
3、高性能のMySQLのインデックスメソッド言及した本は、読み取り専用
最適化SQLの前に:
- SELECT C1 、C2 、CN ... last_active LIMIT BYメンバーORDER FROM 50 、5
最適化されたSQL:
- SELECT C1 、 C2 、 CN ... 。
- メンバーから
- INNER JOINは (last_active限界によって部材順序とMEMBER_ID SELECT 50 、5 )
- 使用した (MEMBER_ID )
インデックスは、読み取ったデータを読み、その後を必要とせずに行を破棄するための違いは、それは、最適化の必要性の前にSQLは、より多くのI / Oを無駄にすることです。その後、SQLその上に(サブクエリピース)最適化された読み取り専用のインデックス(カバーインデックス)、およびMEMBER_IDで必要な列を読み込みます。
図4に示すように、プログラムIDを読み取る第一工程、及びで所望のレコードを読み取るための、方法
プログラムIDを読み取ります。
- 表LIMIT FROM SELECT ID 20000 、10 。
- SELECT C1 、 C2 、 CN ... 。 テーブルFROM WHERE IDが (ID1 、 ID2 、 IDN ... 。)
==============
MySQLの性能とページングクエリの解析と最適化の使用を制限
A、制限用法
当社は、中間前の数やデータの数行にそれを行うにはどのようにこの時間を返すために、多くの場合、クエリを使用する場合は?ない心配を行い、MySQLは、すでに私たちのために、このようなAの機能を提供します。
SELECT * FROM table LIMIT [offset,] rows | `rows OFFSET offset ` (LIMIT offset, `length`) SELECT * FROM table where condition1 = 0 and condition2 = 0 and condition3 = -1 and condition4 = -1 order by id asc LIMIT 2000 OFFSET 50000
LIMIT句はSELECT文の指定された数のレコードを返すを強制するために使用することができます。LIMITは、1つのまたは2つの数値パラメータを取ります。引数は整数定数でなければなりません。二つのパラメータ、所定の第1パラメータを指定し、最初の行のレコードに戻り偏移量
、第二引数は、指定した行の最大数を返します。初始记录行的偏移量是 0(而不是 1)
:PostgreSQLのとの互換性のために、MySQLはまた、構文をサポートしています。LIMIT#が#を相殺しました。
mysql> SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15
//オフセットレコードセットへの一方の端部からすべての行を取得するには、2番目のパラメータは指定でき-1:
mysql> SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.
//返される行の最大数を表す一つのパラメータのみ、与えられる:mysql> SELECT * FROM table LIMIT 5;
//最初の行5取り出す
すなわち//、LIMIT n
に相当します LIMIT 0,n
。
第二に、ページングMySQLのクエリ分析のパフォーマンス
多くのことを見てとてもエレガントなMySQLのLIMIT構文に比べとしてMySQLページングSQL文、TOPの構文とMSSQL場合。ページングするためにそれを使用する最も自然なことです。
最も基本的な方法ページング:
SELECT ... FROM ... WHERE ... ORDER BY ... LIMIT ...
このようSQL、十分な、そして唯一の問題など、少量のデータの場合、インデックスの使用に注意することを確認することです。
たとえば、次のような実際のSQL文が、その後CATEGORY_ID場合、2つの複合索引作成上のIDより良いです:
SELECT * FROM articles WHERE category_id = 123 ORDER BY id LIMIT 50, 10
ページネーションサブクエリ:
データが増加し、より多くのページ、SQL数ページの量が、それは次のようになります表示した後:
SELECT * FROM記事BY ORDERをCATEGORY_ID WHERE、10言及したID = 123 LIMIT 10000以上
一言で言えば、それはより後方にあるLIMIT语句的偏移量就会越大,速度也会明显变慢
ページング。
次のようにこの時点で、我々は、サブクエリを経由してページング効率を向上させることができます。
SELECT * FROM articles WHERE id >= (SELECT id FROM articles WHERE category_id = 123 ORDER BY id LIMIT 10000, 1) LIMIT 10
ページネーションを登録しよう
SELECT * FROM `content` AS t1 JOIN (SELECT id FROM `content` ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) AS t2 WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT $pagesize;
基本的なレベルでのページングとページングサブクエリの効率を参加私のテストの後、時間の消費は基本的に同じです。
SQL文を説明します。
id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY <derived2> system NULL NULL NULL NULL 1 1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 6264 Using where 2 DERIVED content index NULL PRIMARY 4 NULL 27085 Using index
なぜこのようにですか?一般的なお問い合わせは、データファイルに行われている間、サブクエリが、インデックスに行われるので、一般的に言えば、インデックスファイルはデータファイルよりもはるかに小さいので、操作がより効率的になります。
実際のパターンは、最も基本的な方法ページング、より大きな百、使用のページネーションサブクエリを使用し、それ未満百ページであるかどうかを判断するなど、双方向ページングに対処するために同様の戦略を使用することができます。
第三には、MySQLのテーブルのために、大量のデータ、非常に深刻なパフォーマンスの問題のLIMITページの存在を使用しています。
最初の30 1000000後のレコードからクエリ:
SQL代码1:平均用时6.6秒 SELECT * FROM `cdb_posts` ORDER BY pid LIMIT 1000000 , 30 SQL代码2:平均用时0.6秒 SELECT * FROM `cdb_posts` WHERE pid >= (SELECT pid FROM `cdb_posts` ORDER BY pid LIMIT 1000000 , 1) LIMIT 30
するフィールドのすべての内容を削除、大量のデータは、第二は、実質的に直接ながら、最初のブロックを横断して除去する必要があり根据索引字段定位后,才取出相应内容
、非常に自然の効率を高めます。最適化の限界は、限界が直接使用されるが、最初のオフセットIDを取得し、データを取得するために直接限界寸法を使用されません。
図から分かるように、オフセットは次のページでは、より大きなLIMIT文になり、両方の速度ギャップがより明白になります。
実用的なアプリケーションは、あなたが最も基本的な方法ページング、百より大きい、使用改ページのサブクエリを使用し、それ未満百ページであるかどうかを判断するために、例えば、双方向ページングモードに対処するための同様の戦略を使用することができます。
最適化のアイデア:避免数据量大时扫描过多的记录
連続したインデックス列インデックスを確保するために、各テーブルは、自己増力フィールドに追加し、インデックスを追加することができます
参考:オフセットmysqlのページングが大きすぎると、SQLの最適化の経験
========
MySQLの単一のテーブル百万データレコードのページのパフォーマンスの最適化
背景:
データが非常に遅いデータアクセス、分析、背景Googleの定期的な報告タイムアウトで、その結果、単一のテーブルに百万を記録するので、特に大規模なページページが遅いではない、ウェブサイトを所有しています。
テスト環境:
私たちは、基本的なSQL文に精通してみましょう、私たちは、基本情報テーブルのテストを見に行くされている次の
infomation_schema使用
TABLES SELECT * FROM WHERE TABLE_SCHEMA = 'DBNAME' AND TABLE_NAME = '製品'
クエリ結果:
上の図から、我々は、基本情報テーブルを見ることができます:
表の行:866 633
バイト5133:各ラインの平均データ長
単一テーブルサイズ:4448700632のバイト
バイトでテーブルの行のサイズと単位について、我々が計算した後ことを知って
平均線の長さを:5Kについては
、単一のテーブルの合計サイズ:4.1グラムの
種類テーブルのフィールドをvarchar型、日時、テキストなど、ID主キーフィールドを持っています
テストテスト
私はプログラムの方法で使用される制限始動、数ページの声明、1.直接:
製品の制限開始から*を選択し、カウント
スタートページが小さいと、何のクエリパフォーマンスの問題はありません、以下のように、私たちは、ページングを開始する10、100、1000年、10000実行時間(ページテイク20)のそれぞれから見て:
製品限界10、20 0.016秒SELECT * FROM
製品限界から選択* 100、20 0.016秒
製品限界1000〜セレクト*、20秒0.047
20 0.094製品限界10000、SELECT * FROM秒
私たちは、最初の記録の増加とともに、また増加した時間は、開始ページ番号とページネーション文の制限を示すことは素晴らしい関係であることを見てきた、そして我々は、変更40ワットのfacie(すなわち、レコードの記録を開始します一般的に約)製品の制限400000、20 3.229秒から選択*
私たちは、最後に記録された時間を見ては取る
、製品の制限866613から選択* 20 37.44 ミャオ族
検索エンジンがページをクロールも不思議は、我々は多くの場合、明らかに、このページの最大ページとして、タイムアウトを報告していない、この時間
の間には耐え難いです。
我々は2つのことを要約することができ、そこから:
録画の開始の位置に1)クエリ時間制限文をに比例している
2)mysqlの制限文は非常に便利ですが、テーブルのレコードの多くは、直接使用するのに適していません。
リミットページネーションへ2.パフォーマンスの最適化問題
ページングクエリースピードアップするために、インデックステーブルの使用をカバーする
文は(インデックスをカバー)のみインデックス列が含まれている場合は、我々はすべてのノウハウを、インデックスクエリの使用は、このような状況はすぐに照会します。
上記のクエリで最適化アルゴリズムやインデックスデータを検索インデックスの使用は、関連するデータに対処するために行く必要はありませんので、これは多くの時間を節約できます。さらに、MySQLはまた、効果をキャッシュの高い同時実行良く使用時に、インデックスキャッシュに関連しています。
この例では、自然にデフォルトの主キーのインデックスが含まれ、idフィールドが主キーであることを知っています。今度は、カバーインデックスクエリ結果を使用する方法を見てみましょう:
:クエリデータの最終ページ(インデックスの使用をカバーするだけのid列を含む)、など私たちの間で、次の
SELECT IDを製品の限界から866 613、20 0.2ミャオ族
約100倍に向上させるために37.44秒のすべての列を照会する相対スピード
我々はすべての列を照会する必要があるのであれば、2つの方法がありますが、一つはID> =の形であり、他方は結合を使用することで、実際の状況を見て:
製品SELECT * FROM WHERE ID> = (製品限界866613から選択IDは、1)制限20
クエリ時間は、HA、0.2秒であり、単に質的な飛躍ああです
もう一つの方法は
、JOIN製品SELECT * FROM(選択製品の制限866613からIDは、20)a.ID = b.id ON B
クエリは時間のような、非常に短いです!
実際には、両方の場所で、原則として、その効果がほとんどです
背景:
データが非常に遅いデータアクセス、分析、背景Googleの定期的な報告タイムアウトで、その結果、単一のテーブルに百万を記録するので、特に大規模なページページが遅いではない、ウェブサイトを所有しています。
テスト環境:
私たちは、基本的なSQL文に精通してみましょう、私たちは、基本情報テーブルのテストを見に行くされている次の
infomation_schema使用
TABLES SELECT * FROM WHERE TABLE_SCHEMA = 'DBNAME' AND TABLE_NAME = '製品'
クエリ結果:
上の図から、我々は、基本情報テーブルを見ることができます:
表の行:866 633
バイト5133:各ラインの平均データ長
単一テーブルサイズ:4448700632のバイト
バイトでテーブルの行のサイズと単位について、我々が計算した後ことを知って
平均線の長さを:5Kについては
、単一のテーブルの合計サイズ:4.1グラムの
種類テーブルのフィールドをvarchar型、日時、テキストなど、ID主キーフィールドを持っています
テストテスト
私はプログラムの方法で使用される制限始動、数ページの声明、1.直接:
製品の制限開始から*を選択し、カウント
スタートページが小さいと、何のクエリパフォーマンスの問題はありません、以下のように、私たちは、ページングを開始する10、100、1000年、10000実行時間(ページテイク20)のそれぞれから見て:
製品限界10、20 0.016秒SELECT * FROM
製品限界から選択* 100、20 0.016秒
製品限界1000〜セレクト*、20秒0.047
20 0.094製品限界10000、SELECT * FROM秒
私たちは、最初の記録の増加とともに、また増加した時間は、開始ページ番号とページネーション文の制限を示すことは素晴らしい関係であることを見てきた、そして我々は、変更40ワットのfacie(すなわち、レコードの記録を開始します一般的に約)製品の制限400000、20 3.229秒から選択*
私たちは、最後に記録された時間を見ては取る
、製品の制限866613から選択* 20 37.44 ミャオ族
検索エンジンがページをクロールも不思議は、我々は多くの場合、明らかに、このページの最大ページとして、タイムアウトを報告していない、この時間
の間には耐え難いです。
我々は2つのことを要約することができ、そこから:
録画の開始の位置に1)クエリ時間制限文をに比例している
2)mysqlの制限文は非常に便利ですが、テーブルのレコードの多くは、直接使用するのに適していません。
リミットページネーションへ2.パフォーマンスの最適化問題
ページングクエリースピードアップするために、インデックステーブルの使用をカバーする
文は(インデックスをカバー)のみインデックス列が含まれている場合は、我々はすべてのノウハウを、インデックスクエリの使用は、このような状況はすぐに照会します。
上記のクエリで最適化アルゴリズムやインデックスデータを検索インデックスの使用は、関連するデータに対処するために行く必要はありませんので、これは多くの時間を節約できます。さらに、MySQLはまた、効果をキャッシュの高い同時実行良く使用時に、インデックスキャッシュに関連しています。
この例では、自然にデフォルトの主キーのインデックスが含まれ、idフィールドが主キーであることを知っています。今度は、カバーインデックスクエリ結果を使用する方法を見てみましょう:
:クエリデータの最終ページ(インデックスの使用をカバーするだけのid列を含む)、など私たちの間で、次の
SELECT IDを製品の限界から866 613、20 0.2ミャオ族
約100倍に向上させるために37.44秒のすべての列を照会する相対スピード
我々はすべての列を照会する必要があるのであれば、2つの方法がありますが、一つはID> =の形であり、他方は結合を使用することで、実際の状況を見て:
製品SELECT * FROM WHERE ID> = (製品限界866613から選択IDは、1)制限20
クエリ時間は、HA、0.2秒であり、単に質的な飛躍ああです
もう一つの方法は
、JOIN製品SELECT * FROM(選択製品の制限866613からIDは、20)a.ID = b.id ON B
クエリは時間のような、非常に短いです!
実際には、両方の場所で、原則として、その効果がほとんどです