I.背景
今日では、交換基の1の生徒が疑問を提起しました。ルック:
:学生は本当にあいまい例のインデックスを取って完全な問い合わせをした後、
これまで我々は、これらの2つのSQLの最大の違いがあることがわかります(選択*)フルフィールドのクエリが、唯一のAクエリの主キー(選択ID)。
この時点で、他の学生は、他のプログラムについて話しましたがされています。
全文は、これは全体の問い合わせがあいまいインデックスを行かせること、言うまでもないインデックス作成します。しかし、このプログラムをカバーするインデックスが、私はそれが背景と一致していると思います:
一般的なインデックスが主キーのみをカバーするインデックスを過ごすことができ照会しながら1は、背景があるため、あいまいクエリフィールドの質問は、通常のインデックスです。
2、およびのみ主キークエリ(ID)は費用がインデックス表示される背景、。
第二に、データの準備やシーンを再現
1、準備テーブルとデータ:
ユーザーテーブルを作成し、通常の携帯電話のインデックスにフィールドを追加します。
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`phone` varchar(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_phone` (`phone`) USING BTREE COMMENT 'phone索引'
) ENGINE=InnoDB AUTO_INCREMENT=200007 DEFAULT CHARSET=utf8;
100 000データの準備の意味の意味:
delimiter ;
CREATE DEFINER=`root`@`localhost` PROCEDURE `iniData`()
begin
declare i int;
set i=1;
while(i<=100000)do
insert into user(name,age,phone) values('测试', i, 15627230000+i);
set i=i+1;
end while;
end;;
delimiter ;
call iniData();
2、SQLの実装は、実行計画を表示します。
explain select * from user where phone like '%156%';
explain select id from user where phone like '%156%';
3.結果:
ID | SELECT_TYPE | テーブル | パーティション | タイプ | possible_keys | キー | key_lenに | REF | 行 | フィルタ | エクストラ |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | ユーザー | すべて | 99927 | 11.11 | どこ使い方 |
ID | SELECT_TYPE | テーブル | パーティション | タイプ | possible_keys | キー | key_lenに | REF | 行 | フィルタ | エクストラ |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | ユーザー | 指数 | index_phone | 36 | 99927 | 11.11 | どこ使い方; インデックスを使用して |
私たちは、2番目のSQLが実際に使用していた示していることがわかりますindex_phone
インデックスを。
しかし、注意してください学生は見つけることがあります。possible_keys
実際には空であります!病気の感染。。。
私は関係prossible_keysとキーについて話すためにここにいます:
図1に示すように、
possible_keys
インデックスが使用されてもよく、key
実際の使用の指標です。図2に示すように、正常である:
key
インデックスが必然的に含まれますpossible_keys
。
そこトリッキーなポイントは次のとおりです(行)を読んで、インデックスを使用せずに、インデックスと行数を使用するのと同じであることが判明!
第三に、検証段階と推測
前述した、possible_keys
とkey
の関係、そして我々はそれを確認するために、通常の撮影のインデックスを使用しています。
次のSQL、すべてではないあいまいクエリが、インデックスを取るの特定であることが保証権利あいまいクエリは、我々はこの時点で個別に見てpossible_keys
とkey
値:
explain select id from user where phone like '156%';
結果:
ID | SELECT_TYPE | テーブル | パーティション | タイプ | possible_keys | キー | key_lenに | REF | 行 | フィルタ | エクストラ |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | ユーザー | 範囲 | index_phone | index_phone | 36 | 49963 | 100 | どこ使い方; インデックスを使用して |
ここではあまりにも明白:
1、possible_keys
それは含まれないkey
インデックスに。
2、およびrows
フルは倍増し、ダウン瞬時には、49963に低下したfiltered
100に達しました。
ステージの推測:
1、まず第一に、select id from user where phone like '%156%';
ので、カバーインデックスは、むしろインデックスを過ごしますindex_phone
。
2、possible_keysがnullの場合、木を見つけるために、インデックスへのアクセスを証明していません。明らかに、select id from user where phone like '%156%';
表示が消えインデックスがあるにもかかわらず、しかし、行数の読み取り行とselect * from user where phone like '%156%';
のインデックスはかかりませんでした行は同じです。
3、我々は、推測することが可能select id from user where phone like '%156%';
であってもインデックスが使用していたカバーとしてのindex_phone
インデックスを、しかし過ごすためにツリー、インデックスツリーをトラバースするだけで、通常の順序を見つけることができませんでした。だから、実際には、SQLフィールドに2つの小さなテーブルは、クエリのパフォーマンスが勇気を召喚する必要があります。
トレース分析によって検証第四に、
私たちはどのように選択するかであるオプティマイザの両方のSQLのトレース解析を使用していました。
1、お問い合わせのフィールド全体:
-- 开启优化器跟踪
set session optimizer_trace='enabled=on';
select * from user where phone like '%156%';
-- 查看优化器追踪
select * from information_schema.optimizer_trace;
ここでは、ライン上でTRACEを見て:
{
"steps": [
{
"join_preparation": {
"select#": 1,
"steps": [
{
"expanded_query": "/* select#1 */ select `user`.`id` AS `id`,`user`.`name` AS `name`,`user`.`age` AS `age`,`user`.`phone` AS `phone` from `user` where (`user`.`phone` like '%156%')"
}
]
}
},
{
"join_optimization": {
"select#": 1,
"steps": [
{
"condition_processing": {
"condition": "WHERE",
"original_condition": "(`user`.`phone` like '%156%')",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "(`user`.`phone` like '%156%')"
},
{
"transformation": "constant_propagation",
"resulting_condition": "(`user`.`phone` like '%156%')"
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "(`user`.`phone` like '%156%')"
}
]
}
},
{
"substitute_generated_columns": {
}
},
{
"table_dependencies": [
{
"table": "`user`",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": [
]
}
]
},
{
"ref_optimizer_key_uses": [
]
},
{
"rows_estimation": [
{
"table": "`user`",
"table_scan": {
"rows": 99927,
"cost": 289
}
}
]
},
{
"considered_execution_plans": [
{
"plan_prefix": [
],
"table": "`user`",
"best_access_path": {
"considered_access_paths": [
{
"rows_to_scan": 99927,
"access_type": "scan", // 顺序扫描
"resulting_rows": 99927,
"cost": 20274,
"chosen": true
}
]
},
"condition_filtering_pct": 100,
"rows_for_plan": 99927,
"cost_for_plan": 20274,
"chosen": true
}
]
},
{
"attaching_conditions_to_tables": {
"original_condition": "(`user`.`phone` like '%156%')",
"attached_conditions_computation": [
],
"attached_conditions_summary": [
{
"table": "`user`",
"attached": "(`user`.`phone` like '%156%')"
}
]
}
},
{
"refine_plan": [
{
"table": "`user`"
}
]
}
]
}
},
{
"join_execution": {
"select#": 1,
"steps": [
]
}
}
]
}
2、主キーのみのクエリ
set session optimizer_trace='enabled=on';
select id from user where phone like '%156%';
-- 查看优化器追踪
select * from information_schema.optimizer_trace;
ここでは、ライン上でTRACEを探し続けて:
{
"steps": [
{
"join_preparation": {
"select#": 1,
"steps": [
{
"expanded_query": "/* select#1 */ select `user`.`id` AS `id` from `user` where (`user`.`phone` like '%156%')"
}
]
}
},
{
"join_optimization": {
"select#": 1,
"steps": [
{
"condition_processing": {
"condition": "WHERE",
"original_condition": "(`user`.`phone` like '%156%')",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "(`user`.`phone` like '%156%')"
},
{
"transformation": "constant_propagation",
"resulting_condition": "(`user`.`phone` like '%156%')"
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "(`user`.`phone` like '%156%')"
}
]
}
},
{
"substitute_generated_columns": {
}
},
{
"table_dependencies": [
{
"table": "`user`",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": [
]
}
]
},
{
"ref_optimizer_key_uses": [
]
},
{
"rows_estimation": [
{
"table": "`user`",
"table_scan": {
"rows": 99927,
"cost": 289
}
}
]
},
{
"considered_execution_plans": [
{
"plan_prefix": [
],
"table": "`user`",
"best_access_path": {
"considered_access_paths": [
{
"rows_to_scan": 99927,
"access_type": "scan", // 顺序扫描
"resulting_rows": 99927,
"cost": 20274,
"chosen": true
}
]
},
"condition_filtering_pct": 100,
"rows_for_plan": 99927,
"cost_for_plan": 20274,
"chosen": true
}
]
},
{
"attaching_conditions_to_tables": {
"original_condition": "(`user`.`phone` like '%156%')",
"attached_conditions_computation": [
],
"attached_conditions_summary": [
{
"table": "`user`",
"attached": "(`user`.`phone` like '%156%')"
}
]
}
},
{
"refine_plan": [
{
"table": "`user`"
}
]
}
]
}
},
{
"join_execution": {
"select#": 1,
"steps": [
]
}
}
]
}
さて、ここでは、両方のSQLのためにどのようなオプティマイザのインデックスの実際の選択を示さなかった、トレース内の解析、見つけることができますが、それだけのショーあなたが使用している順次走査データを見つけるために方法を。
他の全表スキャン通常のインデックスを使用している間、主キーインデックスを使用してスキャン全表;:おそらく唯一の違いは、それはあるが、2つはB +木の特性上無用である、見つけるためにツリーを費やすことはありませんでしたクエリのパフォーマンスを向上させます。
第六に、締結
図1に示すように、主キーとしてのみファジークエリ結果セットの完全なSQLクエリは、カバーインデックスので、インデックスがクエリのフィールドに対応する過ごすことになります。
2、インデックスが使用していたが、特性を過ごすために木が、トラバーサルの正常な秩序を見つけることができなかった場合でも。
図3に示すように、通常のフル・テーブル・スキャンは、実際には、両方の性能が実際には同じであるので、こと、トラバーサルの順序の主キーインデックスです。