無料PHPプログラム

MySQL 5.1 リファレンスマニュアル :: 6 最適化 :: 6.2 SELECTステートメントおよびその他のクエリの最適化 :: 6.2.4 WHERE 節最適化
« 6.2.3 SELECTクエリの速度

6.2.5 Range 最適化 »
Section Navigation      [Toggle]
  • 6.2 SELECTステートメントおよびその他のクエリの最適化
  • 6.2.1 EXPLAINを使用して、クエリを最適化する
  • 6.2.2 クエリパフォーマンスの推定
  • 6.2.3 SELECTクエリの速度
  • 6.2.4 WHERE 節最適化
  • 6.2.5 Range 最適化
  • 6.2.6 インデックス結合最適化
  • 6.2.7 IS NULL最適化
  • 6.2.8 DISTINCT最適化
  • 6.2.9 LEFT JOINとRIGHT JOIN最適化
  • 6.2.10 入れ子結合最適化
  • 6.2.11 外側Join 単純化
  • 6.2.12 ORDER BY最適化
  • 6.2.13 GROUP BY最適化
  • 6.2.14 LIMITの最適化
  • 6.2.15 テーブルスキャンを避ける方法
  • 6.2.16 INSERTステートメントの速度
  • 6.2.17 UPDATEステートメントの速度
  • 6.2.18 DELETEステートメントの速度
  • 6.2.19 その他の最適化のヒント

6.2.4. WHERE 節最適化

このセクションではWHERE節をプロセスする際の最適化方法を記述します。WHERE の最適化は、ほとんどの場合 SELECTとともに使用されるため、SELECT部分に適用されますがDELETEや UPDATE のステートメントの WHEREにも同じ最適化が適用されます。

また、このセクションは完全なものではないため、注意が必要です。MySQL は多様な最適化を実行するため、すべてを文書化するには時間が足りませんでした。

MySQL によって実行される最適化の一部をここに紹介します

  • 不要なかっこの削除。

       ((a AND b) AND c OR (((a AND b) AND (c AND d))))
    -> (a AND b AND c) OR (a AND b AND c AND d)
    
  • 定数の折りたたみ。

       (a<b AND b=c) AND a=5
    -> b>5 AND b=c AND a=5
    
  • 定数条件の削除(定数の折りたたみに必要)。

       (B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)
    -> B=5 OR B=6
    
  • インデックスが使用する定数式が評価されるのは、1 回に限られる。

  • COUNT(*) WHEREがない単一テーブルの COUNT(*) は、MyISAMと HEAP テーブルのテーブル情報から直接取り出される。 これは、テーブル 1 つのみで使用する場合はすべての NOT NULL式でも実行される。

  • 無効定数式の早期検出。MySQL は実行不可能な SELECTステートメントがある場合、それを迅速に検出し、結果としてレコードを返さない。

  • GROUP BYまたはグループ関数(COUNT()、MIN())を使用しない場合、HAVINGは WHEREとマージされる。

  • サブ結合のそれぞれに、単純な WHEREが構造化され、サブ結合ごとに迅速に WHERE評価を取得し、可能な限り迅速にレコードをスキップする。

  • クエリ内の他のすべてのテーブルの前に、まず、すべての定数テーブルが読み込まれる。定数テーブルとは以下のものを指す。

    • 空白テーブルまたは 1 行のみのテーブル。

    • UNIQUEインデックスまたは PRIMARY KEYを使う WHERE節とともに使用されるテーブルで、インデックス部分のすべてが定数式とともに使用され、そのインデックス部分が NOT NULLとして定義されている場合。

    以下のテーブルはすべて定数テーブルとして使用される。

    SELECT * FROM t WHERE primary_key=1;
    SELECT * FROM t1,t2
      WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
    
  • テーブルを結合する最適な結合の組み合わせは、すべての可能性を試行してみることで発見される。ORDER BYおよび GROUP BY内の全てのカラムが 1 つのテーブルに存在する場合、結合を行う時は第一にこのテーブルが選ばれる。

  • ORDER BY節とそれと異なる GROUP BY節がある場合、あるいは、ORDER BYまたは GROUP BYに結合キューの第 1 テーブルとは異なるテーブルのカラムが含まれている場合は、テンポラリテーブルが作成される。

  • SQL_SMALL_RESULTを使用する場合、MySQL ではメモリ内のテンポラリテーブルが使用される。

  • オプティマイザがテーブルスキャンをしたほうが効率的と判断しない限り、テーブルインデックスごとにクエリが行われ、スパンがレコードの 30% 以上である最適インデックスが使用される。しかし、現在では一定の率でインデックスかスキャンを使用するか判断されます。今バージョンのオプティマイザはより複雑で、テーブルサイズ、行数、そしてI/Oブロックサイズを基準に推定します。

  • 状況によっては、MySQL でデータファイルの参照もせずにインデックスからレコードを読み取れる場合もある。インデックスから使用されるカラムのすべてが数値型の場合、クエリの解決にはインデックスツリーのみが使用される。

  • レコードのそれぞれが出力される前に、HAVING節と一致しないレコードはスキップされる。

非常に高速なクエリのサンプルをいくつか紹介します。

SELECT COUNT(*) FROM tbl_name;

SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;

SELECT MAX(key_part2) FROM tbl_name
  WHERE key_part1=constant;

SELECT ... FROM tbl_name
  ORDER BY key_part1,key_part2,... LIMIT 10;

SELECT ... FROM tbl_name
  ORDER BY key_part1 DESC, key_part2 DESC, ... LIMIT 10;

MySQLは次のクエリで、インデックスツリーのみを使用して解決します(インデックスのあるカラムが数値型であると想定)。

SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;

SELECT COUNT(*) FROM tbl_name
  WHERE key_part1=val1 AND key_part2=val2;

SELECT key_part2 FROM tbl_name GROUP BY key_part1;

次のクエリは、ソートのパスを分けることなく、ソートしたレコードを取り出すためにインデックスを使用します。

SELECT ... FROM tbl_name
  ORDER BY key_part1,key_part2,... ;

SELECT ... FROM tbl_name
  ORDER BY key_part1 DESC, key_part2 DESC, ... ;
Copyright c 1997, 2010, Oracle and/or its affiliates. All rights reserved. Legal Notices
Top / Previous / Next / Up / Table of Contents
© 2010, Oracle Corporation and/or its affiliates

無料CGI PHPスクリプト | 新着情報スクリプト | 営業日カレンダー | PHPマニュアル | MySQLマニュアル | PEARマニュアル

Copyright (c) 2010 jmcodex.com All rights reserved.