Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
EPUB - 7.5Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


8.2.1.1 SELECT ステートメントの速度

クエリーの最適化の主な考慮事項は次のとおりです。

  • 遅い SELECT ... WHERE クエリーを高速化するため、最初に確認することは、インデックスを追加できるかどうかです。WHERE 句で使用するカラムにインデックスをセットアップし、評価、フィルタリング、および最終的な結果の取得を高速化します。無駄なディスク領域を避けるため、アプリケーションで使用される多くの関連クエリーを高速化する少数のインデックスのセットを構築します。

    インデックスは、結合外部キーなどの機能を使用して、さまざまなテーブルを参照するクエリーに特に重要です。EXPLAIN ステートメントを使用して、SELECT に使用するインデックスを判断できます。セクション8.3.1「MySQL のインデックスの使用の仕組み」およびセクション8.8.1「EXPLAIN によるクエリーの最適化」を参照してください。

  • 過度な時間がかかる関数呼び出しなどのクエリーの部分を特定し、チューニングします。クエリーの構築の仕方によっては、関数が結果セットのすべての行に対して 1 回ずつ、さらにはテーブル内のすべての行に対して 1 回ずつ呼び出されるなど、大幅に非効率性を拡大させていることがあります。

  • 特に大きなテーブルの場合に、クエリーでの完全テーブルスキャンの回数を最小にします。

  • ANALYZE TABLE ステートメントを定期的に使用して、テーブル統計を最新に維持し、オプティマイザが、効率的な実行プランを立てるために必要な情報が得られるようにします。

  • チューニング技法、インデックス作成技法、および各テーブルのストレージエンジンに固有の構成パラメータについて学習します。InnoDBMyISAM のどちらでも、クエリーの高いパフォーマンスを可能にし、維持するための一連のガイドラインがあります。詳細については、セクション8.5.5「InnoDB クエリーの最適化」およびセクション8.6.1「MyISAM クエリーの最適化」を参照してください。

  • 特に、MySQL 5.6.4 以上では、セクション14.13.14「InnoDB の読み取り専用トランザクションの最適化」の技法を使用して、InnoDB テーブルの単一クエリートランザクションを最適化できます。

  • 特にオプティマイザで同じ変換の一部を自動的に実行する場合、理解が困難になるようなクエリーの変換を避けます。

  • いずれかの基本ガイドラインによって、パフォーマンスの問題が簡単に解決されない場合、EXPLAIN プランを読み、インデックス、WHERE 句、結合句などを調整して、特定のクエリーの内部の詳細を調査します。(ある程度の専門技術に達している場合は、EXPLAIN プランを読むことがすべてのクエリーの最初の手順になると考えられます。)

  • MySQL がキャッシュに使用するメモリー領域のサイズとプロパティーを調整します。InnoDB バッファープールMyISAM キーキャッシュ、および MySQL クエリーキャッシュの効率的な使用によって、2 回目以降、メモリーから結果が取得されるため、繰り返しのクエリーの実行が高速化します。

  • キャッシュメモリー領域を使用して高速に実行するクエリーでも、必要なキャッシュメモリーを減らして、アプリケーションがよりスケーラブルになるように、さらに最適化できます。スケーラビリティーは、パフォーマンスを大幅に低下させずに、アプリケーションでより多くの同時ユーザー、大きなリクエストなどを処理できることを意味します。

  • クエリーの速度が、テーブルに同時にアクセスしているほかのセッションによって影響を受ける可能性があるロックの問題を処理します。


User Comments
  Posted by Alec Matusis on June 11, 2006
If you need to fetch a small number of rows from a table with 10s of millions of rows, LIMIT offset, n_rows will become increasingly slow as offset increases.

A way around this is to have a unique index that numbers the rows, and base your offset on that index. Example:

SELECT * FROM very_long_table WHERE id > 20000000 LIMIT 20;

is MUCH faster than

SELECT * FROM very_long_table LIMIT 20000000, 20;
  Posted by Stanciu Ionut on February 6, 2007
SELECT * FROM very_long_table WHERE id > 20000000 LIMIT 20;

is MUCH faster than

SELECT * FROM very_long_table LIMIT 20000000, 20;

But it`s not the same thing ...
  Posted by Biswajit Maji on September 24, 2013
these two are not same because it may not have all row entries from 1 to 20000000

  Posted by Awlad Hossain on October 30, 2013
1. SELECT * FROM very_long_table WHERE id > 20000000 LIMIT 20;
2. SELECT * FROM very_long_table LIMIT 20000000, 20;
Indeed the #1 is faster, the #2 is fetching the record for 20000000 + 20 lines from which last 20 records will be shown. And there's a chance that no record will be shown if the case is some records were deleted from the table.

  Posted by Vijay Kumar Sati on March 3, 2015
1. SELECT * FROM very_long_table WHERE id > 20000000 LIMIT 20;

2. SELECT * FROM very_long_table LIMIT 20000000, 20;

Both queries are different and have different outcomes.

1st Query: Will fetch all rows where id > 20000000 and then limit display of records to 20.

2nd Query: Will select all the records from very_long_table(maybe unordered way) and then from the fetched records show the 20 records after the 20000000th record. So it may fetch a record with id = 10000 too as records are unordered.

Solution: "Use ORDER BY id" in both queries to have the same result.

Note: Also for this case we've to assume that column id is primary key and must has values in range [0 - infinite] and no record is deleted from the table(Such a rare case).

So both queries can't be used for same purpose in a generalized manner.
Sign Up Login You must be logged in to post a comment.