explainどのフィールドを覚えていますか.それぞれどんな意味がありますか.

9135 ワード

explain xxxでsql文の性能を分析することはよく知られていますが、explainの結果からどのように性能と各フィールドの意味を分析するか知っていますか.ここで私は総括的な記録をして、自分の後で参考にします.
  • まず注意しなければならない:MYSQL 5.6.3以前はEXPLAIN SELECTしかなかった.MYSQL5.6.3以降はEXPLAIN SELECT,UPDATE,DELETE
  • explain結果の例:
     
    mysql> explain select * from staff;
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    |  1 | SIMPLE      | staff | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    1 row in set
    

    まず前の公式文書表の中国語版:
    Column
    意味
    id
    クエリー番号
    select_type
    クエリーのタイプ
    table
    テーブル名
    partitions
    一致するパーティション
    type
    joinタイプ
    prossible_keys
    選択可能なインデックス
    key
    実際に選択したインデックス
    key_len
    索引の長さ
    ref
    索引と比較する列
    rows
    取得するローの数(推定値)
    filtered
    クエリー条件フィルタの行数の割合
    Extra
    追加情報
    これはexplain結果の各フィールドで、それぞれの意味を説明します.
    1. id
    SQLクエリのシリアル番号.
    id列の数字が大きいほど先に実行し,数字が同じ大きさであれば上から順に実行する.
    2. select_type
    クエリーのタイプは、次の表のいずれかです.
    select_type
    タイプの説明
    SIMPLE
    単純SELECT(UNIONまたはサブクエリを使用しない)
    PRIMARY
    最外層のSELECT
    UNION
    UNIONの2番目以降のSELECT文
    DEPENDENT UNION
    UNIONの2番目以降のSELECT文は、外部のクエリに依存します.
    UNION RESULT
    ユニオンの結果
    SUBQUERY
    サブクエリの最初のSELECT
    DEPENDENT SUBQUERY
    サブクエリの最初のSELECTは、外部クエリに依存します.
    DERIVED
    派生テーブル(FROM句のサブクエリ)
    MATERIALIZED
    物理サブクエリ
    UNCACHEABLE SUBQUERY
    結果セットがキャッシュできないサブクエリは、外部クエリの各ローを再評価する必要があります.
    UNCACHEABLE UNION
    UNIONの2番目以降のSELECTは、キャッシュできないサブクエリに属します
    DEPENDENTは、関連サブクエリが使用されていることを意味します.
    3. table
    クエリーのテーブル名.必ずしも実在するテーブル名ではありません.次の値を指定できます.
  • :idがMとN UNIONの結果を参照します.
  • :idがNの結果から派生したテーブルを参照します.派生テーブルは、FROMサブクエリから派生した結果などの結果セットとすることができる.
  • :idがNのサブクエリ結果を参照して物体化したテーブル.つまり、サブクエリを保存するテンポラリ・テーブルの結果が生成されます.

  • 4.type(重要)
    これは、クエリがどのタイプを使用しているかを示す最も重要なフィールドの1つです.最良から最悪までの接続タイプは、次のとおりです.
    system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,unique_subquery,index_subquery,range,index,ALL
    all以外のtypeはindex_を除いてインデックスに使用できます.merge以外のtypeは1つのインデックスしか使用できません.
  • 1、system

  • テーブルには1行のデータまたは空のテーブルしかありません.これはconstタイプの特例です.myisamテーブルとmemoryテーブルでのみ使用できます.Innodbエンジンテーブルの場合、type列は通常allまたはindexです.
  • 2、const

  • 最大1行のレコードのみが一致します.結合プライマリ・キーまたは一意インデックスのすべてのフィールドが定数値と比較される場合、joinタイプはconstです.他のデータベースはユニークインデックススキャンとも呼ばれます
  • 3、eq_ref

  • マルチテーブルjoinの場合、前のテーブルからの各ローに対して、現在のテーブルには1つのローしか見つかりません.これはシステムとconst以外に最高のタイプかもしれません.このタイプは、プライマリ・キーまたはNULL以外のインデックスのすべてのフィールドがjoin結合として使用される場合に使用されます.
    eq_refは、'='オペレータを使用して比較するインデックス列に使用できます.比較された値は、定数であってもよいし、このテーブルの前に読み込まれたテーブルのカラムを使用する式であってもよい.
    次のrefとの違いは、プライマリ・キーまたはユニーク・インデックスとして使用される一意のインデックスであり、refは非ユニーク・インデックスまたは通常のインデックスを使用します.eq_refは1行しか見つからないが、refは複数行を見つけることができる.
  • 4、ref

  • 前のテーブルからのローごとに、このテーブルのインデックスに複数のローを一致させることができます.結合がインデックスにのみ使用される左の接頭辞またはインデックスがプライマリ・キーまたは一意のインデックスではない場合は、refタイプを使用します(つまり、この結合は複数のロー・レコードに一致します).
    refは、'='または'<=>'オペレータを使用して比較するインデックス列に使用できます.
  • 5、 fulltext

  • 全文インデックスを使用する場合はこのタイプです.全文インデックスの優先度が高いことに注意してください.全文インデックスと通常インデックスが同時に存在する場合、mysqlは代価にかかわらず、全文インデックスを優先的に使用します.
  • 6、ref_or_null

  • refタイプと同様にnull値の比較を増やしただけです.実際にはあまり使われていません.
     
    eg.
    SELECT * FROM ref_table
    WHERE key_column=expr OR key_column IS NULL;
    
  • 7、index_merge

  • クエリが2つ以上のインデックスを使用していることを示し、最後に交差または並列セットを取り、一般的なand,orの条件は異なるインデックスを使用しており、公式ソートはref_or_null以降ですが、実際には複数のインデックスを読み込むため、パフォーマンスのほとんどがrangeに及ばない場合があります.
  • 8、unique_subquery

  • whereのin形式のサブクエリで使用され、サブクエリは重複しない一意の値を返し、サブクエリを完全に置き換えることができ、より効率的です.このタイプは、次の形式のINサブクエリのref:value IN (SELECT primary_key FROM single_table WHERE some_expr)を置き換えます.
  • 9、index_subquery

  • この結合タイプはunique_に似ています.subquery.ユニークでないインデックスに適用され、重複値を返すことができます.
  • 10、range

  • インデックス範囲クエリーは、=,<>,>,>=,BETWEEN,IN()またはlikeなどの演算子を使用するクエリーでよく使用されます.
     
    SELECT * FROM tbl_name
      WHERE key_column BETWEEN 10 and 20;
    
    SELECT * FROM tbl_name
      WHERE key_column IN (10,20,30);
    
  • 11、index

  • インデックス全テーブルをスキャンし、インデックスを最初から最後までスキャンします.ここでは、クエリが上書きインデックスを使用している場合と、インデックスをスキャンするだけでデータを取得できます.これは、インデックスが通常データテーブルよりも小さく、二次クエリを回避できるため、全テーブルスキャンよりも高速です.extraにUsing indexが表示されますが、逆にインデックス上でフルテーブルスキャンを行うと、Using indexのヒントはありません.
     
    #       name   。
    #       name     ,      type   index
    mysql> explain select name from testa;
    +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
    | id | select_type | table | type  | possible_keys | key      | key_len | ref  | rows | Extra       |
    +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
    |  1 | SIMPLE      | testa | index | NULL          | idx_name | 33      | NULL |    2 | Using index |
    +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
    1 row in set
    
    #       cusno     ,              ,       ALL  ,  :
    mysql> explain select cusno from testa;
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    |  1 | SIMPLE      | testa | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    1 row in set
    
    #          
    mysql> explain select * from testa;
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    |  1 | SIMPLE      | testa | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    1 row in set
    
  • 12、all

  • 全表スキャンで、性能が最悪です.
    5. partitions
    バージョン5.7以前はexplain partitionsに表示されていたオプションで、5.7以降はデフォルトのオプションとなっていました.この列には、パーティション・テーブルがヒットしたパーティションの状況が表示されます.非パーティションテーブルこのフィールドは空です(null).
    6. possible_keys
    クエリーで使用可能なインデックスはここにリストされます.
    7. key
    本当に使用されているインデックスをクエリーします.select_typeはindex_mergeの場合、ここに2つ以上のインデックスが表示され、他のselect_typeここには1つしか現れません.
    8. key_len
    クエリに使用されるインデックスの長さ(バイト数).単一のカラム・インデックスの場合は、インデックス全体の長さを計算します.複数のカラム・インデックスの場合、クエリーがすべてのカラムに使用されるとは限りません.いくらで計算されますか.このカラムの値に注意して、複数のカラムインデックスの合計長を計算すると、すべてのカラムに使用されているかどうかがわかります.
    key_lenはwhere条件で使用されるインデックスの長さのみを計算し、ソートとパケットはインデックスを使用してもkey_は計算されません.lenで.
    9. ref
    定数等値クエリーを使用している場合はconst、接続クエリーの場合は被駆動テーブルの実行計画ドライバテーブルの関連フィールド、条件が式または関数を使用している場合は条件列に内部暗黙的な変換が発生している場合はfuncとして表示されます
    10.rows(重要)
    rowsも重要なフィールドです.これはmysqlが推定するスキャンが必要な行数です(正確な値ではありません).この値はSQLの効率の良し悪しを非常に直感的に示しており、原則的にrowsが少ないほど良い.
    11. filtered
    このフィールドは、ストレージエンジンが返すデータがserverレイヤでフィルタリングされた後、クエリのレコード数を満たす割合を示し、パーセンテージであり、特定のレコード数ではないことに注意します.このフィールドは重要ではありません
    12.extra(重要)
    EXplainの追加情報の多くはExtraフィールドに表示されます.一般的には、次のようなものがあります.
  • distinct:selectセクションでdistincキーワード
  • を使用
  • Using filesort:ExtraにUsing filesortがある場合、MySQLは追加のソート操作が必要であることを示し、インデックス順でソート効果を達成できない.一般にUsing filesortがあるが、このようなクエリCPUのリソース消費が大きいため、最適化は排除することを提案する.

  •  
    #        :
    
    mysql> EXPLAIN SELECT * FROM order_info ORDER BY product_name \G
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: order_info
       partitions: NULL
             type: index
    possible_keys: NULL
              key: user_product_detail_index
          key_len: 253
              ref: NULL
             rows: 9
         filtered: 100.00
            Extra: Using index; Using filesort
    1 row in set, 1 warning (0.00 sec)
          
    
    KEY `user_product_detail_index` (`user_id`, `product_name`, `productor`)
               product_name    ,             ,       Using filesort.
                ORDER BY user_id, product_name,         Using filesort  .   :
    
    mysql> EXPLAIN SELECT * FROM order_info ORDER BY user_id, product_name \G
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: order_info
       partitions: NULL
             type: index
    possible_keys: NULL
              key: user_product_detail_index
          key_len: 253
              ref: NULL
             rows: 9
         filtered: 100.00
            Extra: Using index
    1 row in set, 1 warning (0.00 sec)
    
  • Using index「インデックススキャンを上書き」は、クエリがインデックスツリーで必要なデータを検索できることを示し、テーブルデータファイルをスキャンする必要はなく、パフォーマンスが良いことを示すことが多い
  • Using temporaryクエリは一時テーブルを使用し、一般的にソート、グループ化、マルチテーブルjoinの場合、クエリの効率が高くなく、最適化を提案する.