I. Antecedentes
Hoy en día, el estudiante un grupo de intercambio planteó una pregunta. Look:
Después, los estudiantes realmente han hecho una investigación completa tomando el índice de ejemplo difusa:
a esto podemos ver que estos dos sql mayor diferencia es: una consulta de campo completo (select *), pero sólo una consultar la clave principal (seleccione ID).
En este punto, hay otros estudiantes hablado de otros programas:
Indización de texto completo no hace falta decirlo, que hacen que toda la investigación vaya índice difusa. Pero el índice que cubre este programa, creo que es consistente con el fondo:
1, debido a que el fondo está la cuestión del campo de consulta difusa es el índice normal, mientras que el índice general sólo consulta la clave primaria puede pasar un índice de cobertura.
2, y el fondo, es decir, solamente la consulta de clave principal (ID) está representada pasar indexado.
En segundo lugar, la preparación de datos y reproducir la escena
1, mesas de preparación y datos:
Crear una tabla de usuario, agregar un campo de índice de teléfono normal:
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 Preparación de datos significado de significado:
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, la implementación de SQL, ver el plan de ejecución:
explain select * from user where phone like '%156%';
explain select id from user where phone like '%156%';
3. Los resultados:
carné de identidad | seleccione tipo | mesa | particiones | tipo | possible_keys | llave | key_len | árbitro | filas | filtrado | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SENCILLO | usuario | TODOS | 99927 | 11.11 | utilizando, cuando |
carné de identidad | seleccione tipo | mesa | particiones | tipo | possible_keys | llave | key_len | árbitro | filas | filtrado | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SENCILLO | usuario | índice | index_phone | 36 | 99927 | 11.11 | Usando donde; utilizando el índice |
Podemos ver que el segundo SQL muestran, de hecho estaban usando index_phone
el índice.
Pero el estudiante cuidadoso puede encontrar: possible_keys
en realidad está vacía! La transmisión de la enfermedad. . .
Estoy aquí para hablar de las relaciones y prossible_keys clave:
1,
possible_keys
el índice puede ser utilizado, ykey
es el índice de uso real;2, el es normal:
key
índice incluyen inevitablemente enpossible_keys
el.
Hay un pequeño truco: con el índice y el número de líneas sin utilizar un índice de lectura (filas) resultó ser el mismo!
En tercer lugar, la etapa de verificación y conjeturas
Se mencionó anteriormente, possible_keys
y key
la relación, entonces usamos la toma normal, el índice de verificarla.
El siguiente código SQL, no todas consulta difusa, pero la consulta difusa derecho, garantizado para estar seguro de tener el índice, que se ven por separado en este momento possible_keys
y key
valores:
explain select id from user where phone like '156%';
Los resultados:
carné de identidad | seleccione tipo | mesa | particiones | tipo | possible_keys | llave | key_len | árbitro | filas | filtrado | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SENCILLO | usuario | rango | index_phone | index_phone | 36 | 49963 | 100 | Usando donde; utilizando el índice |
Aquí también obvia:
1, possible_keys
donde no incluyen key
en el índice.
2, y rows
al instante se redujo a 49.963, por un total duplicó y filtered
llegó a 100.
Etapa conjetura:
1, en primer lugar, select id from user where phone like '%156%';
debido a que el índice de cobertura y no gastar el índice index_phone
.
2, possible_keys es nula, demostrado ningún acceso al índice para encontrar el árbol. Obviamente, select id from user where phone like '%156%';
aunque la pantalla es el índice se ha ido, pero lee el número de filas filas y select * from user where phone like '%156%';
no tomaron el índice de filas es el mismo.
3, entonces podemos suponer, select id from user where phone like '%156%';
aun cuando los índices que cubren estaban usando index_phone
el índice, pero no pudieron encontrar un árbol para pasar, sólo el orden normal de recorrer el árbol de índice. Así que, de hecho, dos pequeñas mesas en el campo SQL, el rendimiento de las consultas deben ser armó de valor.
En cuarto lugar, verificado por análisis de trazas
Estábamos usando el análisis de seguimiento para SQL Optimizer es cómo elegir.
1, todo el campo de la investigación:
-- 开启优化器跟踪
set session optimizer_trace='enabled=on';
select * from user where phone like '%156%';
-- 查看优化器追踪
select * from information_schema.optimizer_trace;
Aquí nos fijamos en TRACE en la línea:
{
"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, sólo la consulta de clave principal
set session optimizer_trace='enabled=on';
select id from user where phone like '%156%';
-- 查看优化器追踪
select * from information_schema.optimizer_trace;
Aquí seguimos mirando TRACE en la línea:
{
"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": [
]
}
}
]
}
Bueno, aquí podemos encontrar, analizar dentro de la traza, no mostraron la elección real de lo que el índice de optimizador para SQL, pero esto demuestra que estamos usando una exploración secuencial método para encontrar los datos.
Probablemente, la única diferencia es que: una tabla de análisis completo utilizando el índice de clave principal, mientras que la otra es usar un índice ordinario escaneo completo de tabla, pero los dos no pasó el árbol de encontrar, que es inútil en las características de la B + Árbol para mejorar el rendimiento de consulta.
En sexto lugar, la conclusión
1, cuando la consulta SQL completo solamente difuso conjunto de resultados de consulta como clave principal, debido a que el índice de la cubierta, el índice gastará campo de consulta correspondiente.
2, incluso si el índice estaban usando, pero no pudo encontrar un árbol para pasar características, pero el orden normal de recorrido.
3, mientras que el escaneo completo de tabla normal es el índice de clave principal de la orden de recorrido, por lo que, de hecho, el rendimiento de ambos es en realidad el mismo.