1 Preparación de datos
1.1 Crear una nueva tabla de datos
CREATE TABLE `player` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`player_id` varchar(256) NOT NULL COMMENT '运动员编号',
`player_name` varchar(256) NOT NULL COMMENT '运动员名称',
`height` int(11) NOT NULL COMMENT '身高',
`weight` int(11) NOT NULL COMMENT '体重',
`type` varchar(256) DEFAULT '0' COMMENT '球员类型',
`game_performance` text COMMENT '最近一场比赛表现',
PRIMARY KEY (`id`),
KEY `idx_name_height_weight` (`player_name`,`height`,`weight`),
KEY `idx_type` (`type`),
KEY `idx_height` (`height`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
复制代码
La tabla de datos anterior declara tres índices:
- Índice conjunto: idx_name_height_weight
- Índice ordinario: idx_type
- Índice normal: idx_height
1.2 Agregar 1 millón de piezas de datos
@SpringBootTest(classes = TestApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class PlayerServiceTest {
@Resource
private PlayerRepository playerRepository;
@Test
public void initBigData() {
for (int i = 0; i < 1000000; i++) {
PlayerEntity entity = new PlayerEntity();
entity.setPlayerId(UUID.randomUUID().toString());
entity.setPlayerName("球员_" + System.currentTimeMillis());
entity.setType("0");
entity.setWeight(150);
entity.setHeight(188);
entity.setGamePerformance("{\"runDistance\":8900.0,\"passSuccess\":80.12,\"scoreNum\":3}");
playerRepository.insert(entity);
}
}
}
复制代码
2 Conocimientos básicos
2.1 tipo de explicación
El tipo de acceso en el plan de ejecución es un indicador de análisis importante:
2.2 Explicación adicional
Extra indica la información de extensión del plan de ejecución:
3 escenarios de falla del índice
Este capítulo presenta diez escenarios de falla del índice:
- tipo de consulta incorrecto
- La columna de índice participa en la operación.
- uso incorrecto de comodines
- Índice de cobertura no utilizado
- O unirse sin campos indexados
- MySQL abandona el uso de índices
- falla del índice conjunto
- índice incompleto
- salto de índice
- emparejamiento de no equivalencia
- falta el índice más a la izquierda
3.1 Tipo de consulta incorrecto
3.1.1 Escenarios de falla
explain select * from player where type = 0
复制代码
3.1.2 Soluciones
La tabla de datos define type
el campo como varchar
un tipo y la consulta debe usar el mismo tipo:
explain select * from player where type = '0'
复制代码
3.2 Las columnas de índice participan en operaciones
3.2.1 Escenarios de falla
explain select * from player where height + 1 > 189
复制代码
3.2.2 Soluciones
explain select * from player where height > 188
复制代码
3.3 MySQL abandona el uso de índices
3.3.1 Escenarios de falla
MySQL encuentra que si el rendimiento de usar un índice es más bajo que el de un escaneo completo de la tabla, dejará de usar el índice. Por ejemplo, todos height
los valores de campo de datos de 1 millón en la tabla son 188
, por lo que el índice se abandona al ejecutar la siguiente instrucción:
explain select * from player where height > 187
复制代码
3.3.2 Solución 1
Ajuste el valor de la condición de consulta:
explain select * from player where height > 188
复制代码
3.3.3 Solución 2
Especificación de índice obligatoria, es posible que este método no mejore necesariamente el rendimiento:
explain select * from player force index(idx_height) where height > 187
复制代码
3.4 Uso incorrecto de comodines
3.4.1 Preparación de datos
Para evitar la falla del Capítulo 3.3, modifique un dato aquí:
update player set player_name = '测试球员' where id = 1
复制代码
3.4.2 Escenario de falla 1
explain select * from player where player_name like '%测试'
复制代码
3.4.3 Escenario de falla 2
explain select * from player where player_name like '%测试%'
复制代码
3.4.4 Soluciones
explain select * from player where player_name like '测试%'
复制代码
3.5 Conexión O sin campo de índice
3.5.1 Escenarios de falla
type
Con índice, weight
sin índice:
explain select * from player where type = '0' or weight = 150
复制代码
3.5.2 Soluciones
weight
Agregar nuevos índices, union
ensamblar y consultar datos
explain
select * from player where type = '0'
union
select * from player where weight = 150
复制代码
3.6 Índice de cobertura no utilizado
3.6.1 Escenarios de falla
Using index condition
Indica que se usa el índice, pero debe devolverse a la tabla para la consulta
explain select * from player where player_name like '测试%'
复制代码
3.6.2 Soluciones
覆盖索引含义是查询时索引列完全包含查询列,查询过程无须回表(需要在同一棵索引树)性能得到提升。Using Index; Using where
表示使用覆盖索引并且用where
过滤查询结果:
explain select id,player_name,height,weight from player where player_name like '测试%'
复制代码
3.7 联合索引失效
3.7.1 完整使用
联合索引idx_name_height_weight
完整使用key_len
=778:
explain select * from player where player_name = '球员_1682577684751' and height = 188 and weight = 150
复制代码
3.7.2 失效场景一:索引不完整
weight
不在查询条件,所以只用到idx_name_height
,所以key_len
= 774:
explain select * from player where player_name = '球员_1682577684751' and height = 188
复制代码
3.7.3 失效场景二:索引中断
height
不在查询条件,所以只用到idx_name
,所以key_len
= 770:
explain select * from player where player_name = '球员_1682577684751' and weight = 150
复制代码
3.7.4 失效场景三:非等值匹配
height
非等值匹配,所以只用到idx_name_height
,所以key_length
=774:
explain select * from player where player_name='球员_1682577684751' and height > 188 and weight = 150
复制代码
3.7.5 失效场景四:最左索引缺失
player_name
最左索引不在查询条件,全表扫描
explain select * from player where weight = 150
复制代码
4 文章总结
本文第一进行测试数据准备,第二介绍执行计划相关知识,第三介绍索引失效10种场景:查询类型错误,索引列参与运算,错误使用通配符,未用到覆盖索引,OR连接无索引字段,MySQL放弃使用索引,联合索引中索引不完整,索引中断,非等值匹配,最左索引缺失。