I. Background
Today, the exchange group one student raised a question. Look:
After, the students really have made a full inquiry taking the index of fuzzy example:
to this we can see that these two sql biggest difference is: a full-field query (select *), but only a query primary key (select id).
At this point, there are other students talked about other programs:
full-text indexing This goes without saying, that make the whole inquiry go fuzzy index. But the index covering this program, I think that is consistent with the background:
1, because the background is the question of fuzzy query field is normal index, while the general index only queries the primary key can spend a covering index.
2, and the background, that is, only the primary key query (ID) displayed spend indexed.
Second, the data preparation and reproduce the scene
1, preparation tables and data:
Create a user table, add a field to ordinary phone index:
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 Data Preparation meaning of meaning:
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, the implementation of SQL, view the execution plan:
explain select * from user where phone like '%156%';
explain select id from user where phone like '%156%';
3. The results:
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | user | ALL | 99927 | 11.11 | Using where |
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | user | index | index_phone | 36 | 99927 | 11.11 | Using where; Using index |
We can see that the second SQL indeed show were using index_phone
the index.
But the careful student may find: possible_keys
actually is empty! Transmission of the disease. . .
I am here to talk about the relationship prossible_keys and key:
1,
possible_keys
the index may be used, andkey
is the index of actual use;2, the normal is:
key
index inevitably included inpossible_keys
the.
There is a little trick: using the index and the number of lines without using an index reading (rows) turned out to be the same!
Third, the verification stage and conjecture
Mentioned above, possible_keys
and key
the relationship, then we use the normal taking the index to verify it.
The following SQL, not all fuzzy query, but the right fuzzy query, guaranteed to be certain of taking the index, we look separately at this time possible_keys
and key
values:
explain select id from user where phone like '156%';
Results of the:
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | user | range | index_phone | index_phone | 36 | 49963 | 100 | Using where; Using index |
Here too obvious:
1, possible_keys
where it does include key
in the index.
2, and rows
instantly dropped to 49,963, down a full doubled and filtered
reached 100.
Stage guess:
1, first of all, select id from user where phone like '%156%';
because the covering index rather spend the index index_phone
.
2, possible_keys is null, proved no access to the index to find the tree. Obviously, select id from user where phone like '%156%';
even though the display is gone index, but read the number of rows rows and select * from user where phone like '%156%';
did not take the index of rows is the same.
3, then we can guess, select id from user where phone like '%156%';
even as covering indexes were using index_phone
the index, but failed to find a tree to spend, just the normal order of traversing the index tree. So, in fact, two small tables in the SQL field, the query performance should be summoned up the courage.
Fourth, verified by Trace Analysis
We were using the Trace analysis for both SQL optimizer is how to choose.
1, the whole field of inquiry:
-- 开启优化器跟踪
set session optimizer_trace='enabled=on';
select * from user where phone like '%156%';
-- 查看优化器追踪
select * from information_schema.optimizer_trace;
Here we look at TRACE on the line:
{
"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, only the primary key query
set session optimizer_trace='enabled=on';
select id from user where phone like '%156%';
-- 查看优化器追踪
select * from information_schema.optimizer_trace;
Here we continue to look TRACE on the line:
{
"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": [
]
}
}
]
}
Well, here we can find, analyze inside the Trace, did not show the actual choice of what the optimizer index for both SQL, but it just shows you are using a sequential scanning method to find the data.
Probably the only difference is that: a full table scan using the primary key index, while the other is to use a full table scan ordinary index; but the two did not spend the tree to find, which is useless on the characteristics of the B + Tree to improve query performance.
Sixth, concluded
1, when the full SQL query only fuzzy query result set as a primary key, because the cover index, the index will spend corresponding query field.
2, even if the index were using, but failed to find a tree to spend characteristics, but the normal order of traversal.
3, while the normal full table scan is the primary key index of the order of traversal, so that, in fact, the performance of both is actually the same.