mysql実行計画の初歩的な解読1


Mysqlの実行計画は、普段の接触が少ない部分です.申し訳ありませんが、普段のsql最適化はsqlを直接見て、条件のdebugを一列に並べて、科学的な統計方法はありません.時間を割いて計画を実行する内容を見て、収穫が豊富だと感じました.実行計画フォーマットまず、実行計画が何であるかを簡単に見てみましょう.簡単な注文と注文商品joinを関連付けた結果:ok、実行計画表は全部で12列あり、各列の意味は、私たちが一つ一つ来ます.1.idは、各句の操作順序を表し、idが大きいほど優先度が高くなる.各レベルのクエリーについて、idは一致し、操作の優先度クエリーを表す.サブクエリのあるsqlでは、サブクエリの優先度が外側クエリよりも高いことがわかります.私たちの主観意識にも合っています.まずサブテーブルを調べてから、メインテーブルを調べることができます.しかし、サブクエリ文を持つすべてのsqlがサブクエリになるわけではありません.例えば、sqlオプティマイザの最適化ルールについては、私はあまり説明しません.1つは、この章の主な内容がこの方面の内容ではなく、2つは私自身が悟っても足りないことです.
2.select_type,クエリタイプ1)SIMPLE,単純クエリ,サブクエリまたはUNIONサブステートメントを含まないことを示す2)PRIMARY,クエリステートメントがサブクエリまたはUNIONサブステートメントを含むことを示す,PRIMARYが外層を表す3)SUBQUEY,サブクエリ文4)UNIONはunionの2番目以降のサブクエリがunion 5としてマークされている)DERIVEDはfromリストに含まれるサブクエリがderived(派生)6としてマークされているDEPENDENT UNIONの2番目または後のSELECT文であり、外のクエリ7に依存する)UNION RESULT UNIONの結果6と7は本人には十分理解されておらず、展示されなくなっている
3.table、クエリー・テーブルが必要です.これはデータベース・テーブルまたはテンポラリ・テーブルの可能性があります.
4.partitions、一致したパーティション、サブテーブルクエリに現れる場合
5.type、アクセスタイプ、この指標はsqlクエリー最適化において重要な指標であり、よく現れるいくつかの列挙値は以下の通りである:system:表には1行の記録しかなく、システム表constに相当する:インデックスによって1回ヒットし、1行のデータeq_に一致するref:一意性インデックススキャン、各インデックスキーに対して、表には1つのレコードしか一致しません.共通語プライマリキーまたは一意インデックススキャンref:非一意性インデックススキャン、ある個別値に一致するすべての行を返します.=、オペレータがインデックスを持つ列range:指定された範囲の行のみを取得し、1つのインデックスを使用して行を選択します.一般的にbetween、index:インデックスツリーのみを巡回します.all:全表スキャン;上から下への実行効率は順次低下し,上位5つのケースはいずれも理想的なインデックスの場合である.通常は少なくともrangeレベルに最適化され、refに最適化されることが望ましい.いくつかの例を列挙します:systemはconstの1つの特例で、表の中で1行のデータしかない時私を使って注文番号の上で唯一のインデックスを創立して、下図(ええ、どうしてピクチャーを伝えることができなくて、直接結果を貼り付けます)を通じて(通って)見ることができて、プライマリ・キーあるいは唯一のインデックスがwhere条件にある時、それでは実行するタイプはconstです
    mysql> explain select * from `order` where title = 'C1086407110000019';
+----+-------------+-------+------------+-------+---------------+--------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type  | possible_keys | key    | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | order | NULL       | const |             |      | 1023    | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+-------+---------------+--------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from `order` where id = 1;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | order | NULL       | const | PRIMARY       | PRIMARY | 8       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

そしてeq_refの違いは、eq_refは、次のように関連クエリーで使用されます.
mysql> explain select * from `order` left join order_item on `order`.id = order_item.order_id where `order`.id = 1;
+----+-------------+------------+------------+-------+---------------+-----------+---------+-------+------+----------+-------+
| id | select_type | table      | partitions | type  | possible_keys | key       | key_len | ref   | rows | filtered | Extra |
+----+-------------+------------+------------+-------+---------------+-----------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | order      | NULL       | const | PRIMARY       | PRIMARY   | 8       | const |    1 |   100.00 | NULL  |
|  1 | SIMPLE      | order_item | NULL       | ref   |            |        | 8       | const |    2 |   100.00 | NULL  |
+----+-------------+------------+------------+-------+---------------+-----------+---------+-------+------+----------+-------+
2 rows in set, 1 warning (0.00 sec)

受注のユーザーidなどの非一意性インデックスでは、refまたはrangeの結果が次のように使用される可能性があります.
mysql> explain select * from `order` where customer_id = 55029;
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | order | NULL       | ref  | customer_id   | customer_id | 8       | const |   10 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from `order` where customer_id > 55029 and customer_id < 55129;
+----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type  | possible_keys | key         | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | order | NULL       | range | customer_id   | customer_id | 8       | NULL |    1 |   100.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

もちろんインデックスのフィールドがなければ、実行方法はALLしかありません.しかし、インデックスがあれば必ずインデックスを付けないわけではないことに注意してください.性別フィールドなどのフィールドの差異が小さすぎる場合、インデックスが作成されてもインデックスは作成されません.ここでは、テストを行うために使用したすべての注文書表に売り手が1人しかいません.このフィールドにはインデックスがありますが、検索してみましょう.
mysql> explain select * from `order` where seller_id = 19;
+----+-------------+-------+------------+------+------------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys    | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+------------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | order | NULL       | ALL  |   ,seller_id   | NULL | NULL    | NULL | 2197 |   100.00 | Using where |
+----+-------------+-------+------------+------+------------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

実際にinnodbはインデックスを選択していないことがわかりました.この場合、インデックスを実行しないよりもインデックスを実行するコストが大きいからです.オーバーヘッドについてはInnodbがCBOに基づいて判断している(より古い判断方法はRBOであり、これらの内容は具体的にはよく覚えていないので、知りたいことはもう少し関連資料を探す必要がある).
上記の値はすべての列挙値ではありません.例えばfulltext、index_もあります.merge、 unique_subqueryなどですが、出現頻度は上記のいくつかの列挙値ほど高くありません.system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL