ツールの紹介を説明する
目次
1.ツールの紹介を説明する
EXPLAINキーワードを使用して、オプティマイザーをシミュレートしてSQLステートメントを実行し、クエリステートメントまたは構造のパフォーマンスのボトルネックを分析します。selectステートメントの前にexplainキーワードを追加します。MySQLはクエリにフラグを設定し、クエリの実行は戻ります。実行計画の情報。このSQLを実行する代わりに。
注:fromにサブクエリが含まれている場合でも、サブクエリは実行され、結果は一時テーブルに配置されます。
1.1。分析例を説明する
次のように3つのテーブルを作成する必要があります。
アクターテーブル:
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `actor`;
CREATE TABLE `actor` (
`id` int(11) NOT NULL,
`name` varchar(45) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `actor` VALUES ('1', 'a', '2017-12-22 15:27:18');
INSERT INTO `actor` VALUES ('2', 'b', '2017-12-22 15:27:18');
INSERT INTO `actor` VALUES ('3', 'c', '2017-12-22 15:27:18');
フィルムテーブル:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `film`
-- ----------------------------
DROP TABLE IF EXISTS `film`;
CREATE TABLE `film` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `film` VALUES ('3', 'film0');
INSERT INTO `film` VALUES ('1', 'film1');
INSERT INTO `film` VALUES ('2', 'film2');
film_actorテーブル:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `film_actor`
-- ----------------------------
DROP TABLE IF EXISTS `film_actor`;
CREATE TABLE `film_actor` (
`id` int(11) NOT NULL,
`film_id` int(11) NOT NULL,
`actor_id` int(11) NOT NULL,
`remark` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_film_actor_id` (`film_id`,`actor_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `film_actor` VALUES ('1', '1', '1', null);
INSERT INTO `film_actor` VALUES ('2', '1', '2', null);
INSERT INTO `film_actor` VALUES ('3', '2', '1', null);
1.2。属性を詳細に説明する
-- 走的是全表扫描
EXPLAIN SELECT * from actor;
注:EXPLAINを使用する場合、一時的にタイプに注意を払います(後で追加されます)
1.1.1。タイプ
この列は、関連付けのタイプまたはアクセスタイプを示します。つまり、MySQLは、テーブル内の行を検索する方法を決定し、データ行レコードのおおよその範囲を検索します。
最良のものから最悪のものまで、システム> const> eq_ref> ref> range> index> ALLです。(SQLの最適化後、クエリが範囲、できればrefをノックダウンすることを確認してください)
注:これを導入する前に、焦点を当てる必要がある特別な状況があります。
NULL: mysqlは最適化フェーズ中にクエリステートメントを分解でき、実行フェーズ中にテーブルまたはインデックスにアクセスする必要はありません。
例:インデックス列の最小値の選択は、実行中にテーブルにアクセスすることなく、インデックスを個別に検索することで実行できます。
EXPLAIN SELECT min(id) from film; -- type 为null 表示单独查找索引就能完成,不需要对表有操作
分析:フィルムテーブルの場合、idが主キーです。このクエリロジックは、主キーをクエリすることで直接実行できます。データはまったくクエリされません(したがって、表示はNullになります)。
ただし、Nullであることは最速を意味するのではなく、実際の状況(データ量psなど:テーブルに数千万のデータがあると仮定すると、id = 1は高速クエリに使用されますか、フルインデックススキャンは最小の高速値を取りますか?)
const、system: mysqlはクエリの特定の部分を最適化し、それを定数に変換できます(showwarningsの結果を参照してください)。
主キーまたは一意キーに使用されるすべての列を定数と比較すると、テーブルには最大で1つの一致する行があり、1回の読み取りが高速です。
systemはconstの特殊なケースであり、テーブルに一致するタプルが1つしかない場合は、systemです。
Explain EXTENDED SELECT * from (select * from film where id = 1) tmp;
解析:主キーの同等の値に従って直接クエリを実行します。SQLパーサーの場合、テーブル内の1つのデータのみが要件を満たします。私にとってはconst(定数)であり、2番目のデータのタイプは次のとおりです。 const(定数))
最初のデータのシステム、私はクエリ結果からデータをクエリしますが、クエリ結果にはデータが1つしかないため、タイプはsystemです(これがsystemがconstの特殊なケースである理由です)
eq_ref:主キーまたは一意キーインデックスのすべての部分が組み合わせて使用され、最大で1つの適格なレコードのみが返されます。これはconst以外の最良のタイプの結合である可能性があり、このタイプは単純な選択クエリには表示されません。
EXPLAIN SELECT * from film_actor LEFT JOIN film on film_actor.film_id = film.id;
理解:最初のデータを最初に見てください。タイプにはすべてが表示されます。つまり、film_actorテーブルのすべてのデータがクエリされます。2番目のデータは、film_actorのIDに従ってフィルムテーブルのIDを関連付けることです。 (映画のIDが主キーです))。
ref: eq_refと比較して、一意のインデックスを使用しませんが、共通のインデックスまたは一意のインデックスの部分プレフィックスを使用します。インデックスを特定の値と比較する必要があり、複数の修飾行が見つかる場合があります。
- 単純な選択クエリ、名前は通常のインデックス(一意でないインデックス)
EXPLAIN select * from film where name = 'film1';
- 関連するテーブルクエリ、idx_film_actor_idはfilm_idとactor_idの共同インデックスであり、ここではfilm_actorの左側のプレフィックスfilm_id部分が使用されます。
Explain SELECT film_id from film LEFT JOIN film_actor on film.id = film_actor.film_id;
理解:フィルムのname属性は通常のインデックスであり、主キーインデックスではなく、インデックスタイプはrefです。
range:範囲スキャンは通常、in()などの操作で、>、<、> =の間で発生します。インデックスを使用して、特定の範囲の行を取得します。
EXPLAIN SELECT * from actor where id > 1;
理解:これは主キーに基づく範囲検索です。また、通常のインデックスを使用して範囲検索を実行しました。最終的なタイプはすべてです。
index:テーブルインデックス全体をスキャンします。これは通常、ALLよりも高速です。
注:インデックスは、フィルムテーブルのすべての属性に対応するインデックスがあるためです。
ALL:全表スキャン。これは、mysqlが最初から最後まで必要な行を見つける必要があることを意味します。通常の状況では、これは最適化するためにインデックスを増やす必要があります
EXPLAIN SELECT * from actor;
(後で追加される他の属性があります)