herramientas de optimización de MySQL (explicar)

Herramienta de explicación Introducción

Uso de palabras clave EXPLAIN puede simular el optimizador para ejecutar sentencias SQL, analizar el cuello de botella en su consulta o palabras clave aumenta explicar la estructura antes de la instrucción de selección, MySQL fijará una marca en la consulta, ejecutar la consulta de información plan de ejecución de las devoluciones, en cambio ejecuta el SQL Nota: si a partir contiene sub-consultas, ejecutará los resultados sub-consulta en una tabla temporal

Explicar análisis Ejemplo 1

Ejemplo Tabla:

Tabla 1

DROP TABLE IF EXISTS `actor`;
CREATE TABLE `actor` (`id` int(11) NOT NULL,
`name` varchar(45) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`)) 
ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `actor` (`id`, `name`, `update_time`) VALUES 
(1,'a','2017‐12‐22 15:27:18'),(2,'b','2017‐12‐22 15:27:18'),(3,'c','2017‐12‐22 15:27:18');

Tabla 2

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 DEFAULT CHARSET=utf8;
INSERT INTO `film` (`id`, `name`) VALUES (3,'film0'),(1,'film1'),(2,'film2');

Tabla 3

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` (`id`, `film_id`, `actor_id`) VALUES (1,1,1),(2,1,2),(3,2,1);

Cada salida de la tabla voluntad una línea en la consulta, si hay dos tablas de consulta de unión por unirse, entonces la salida será de dos líneas

explicar dos variantes

1) explicar extendido : la optimización de consultas extra proporcionar alguna información sobre la base de explicar. Seguido de la consulta puede ser optimizada mediante comandos show advertencias para ver lo que la optimización optimizador

Primaria consulta clave:

explain select * from pea_goods where pea_goods_Id=190919181614003;

salida

carné de identidad seleccione tipo mesa particiones tipo possible_keys llave key_len árbitro filas filtrado Extra
1 SENCILLO pea_goods const PRIMARIO PRIMARIO 8 const 1 100.00

mostrar advertencias;

salida

Nivel Código Mensaje
Nota 1003 / * SELECT * #. 1 / SELECT '190.919.181.614.003' el AS pea_goods_id, '190.919.145.343.001' el AS pea_supplier_id, '190.919.175.230.001' el AS pea_customer_id, 'estazolam' el AS goods_name, 'XXX007' el AS goods_code, '10' el AS goods_type,' t 'el AS goods_unit, el AS NULL safe_date,' 100 'AS width', 100 'AS length', 100 'AS height', 100 'AS weight, AS NULL volume,' 10000.08 'AS price' 30/10/2019 23:59:59 'AS warranty' 30' AS allowed_day', peligrosa, cuidadosamente sopladas 'el AS description, el AS NULL line_no, la Y 'el AS is_active,' 190.815.135.958.005 'el AS created_by,' 09/19/2019 18:16:14 'el AS created,' 190.815.135.958.005 'el AS updated_by,' 10/10/2019 16:53:02 'el AS updated, '190.815.135.742.002' AS ad_client_idpartir vip_tulin.pea_goodsdonde 1

consulta clave no primaria

explain select * from pea_goods where pea_customer_id=190919175230001;

salida

carné de identidad seleccione tipo mesa particiones tipo possible_keys llave key_len árbitro filas filtrado Extra
1 SENCILLO pea_goods TODOS 50 10.00 Utilizando dónde

mostrar advertencias;

salida

Nivel Código Mensaje
Nota 1003 / *
select#1 */ select `vip_tulin`.`pea_goods`.`pea_goods_id` AS `pea_goods_id`,`vip_tulin`.`pea_goods`.`pea_supplier_id` AS `pea_supplier_id`,`vip_tulin`.`pea_goods`.`pea_customer_id` AS `pea_customer_id`,`vip_tulin`.`pea_goods`.`goods_name` AS `goods_name`,`vip_tulin`.`pea_goods`.`goods_code` AS `goods_code`,`vip_tulin`.`pea_goods`.`goods_type` AS `goods_type`,`vip_tulin`.`pea_goods`.`goods_unit` AS `goods_unit`,`vip_tulin`.`pea_goods`.`safe_date` AS `safe_date`,`vip_tulin`.`pea_goods`.`width` AS `width`,`vip_tulin`.`pea_goods`.`length` AS `length`,`vip_tulin`.`pea_goods`.`height` AS `height`,`vip_tulin`.`pea_goods`.`weight` AS `weight`,`vip_tulin`.`pea_goods`.`volume` AS `volume`,`vip_tulin`.`pea_goods`.`price` AS `price`,`vip_tulin`.`pea_goods`.`warranty` AS `warranty`,`vip_tulin`.`pea_goods`.`allowed_day` AS `allowed_day`,`vip_tulin`.`pea_goods`.`description` AS `description`,`vip_tulin`.`pea_goods`.`line_no` AS `line_no`,`vip_tulin`.`pea_goods`.`is_active` AS `is_active`,`vip_tulin`.`pea_goods`.`created_by` AS `created_by`,`vip_tulin`.`pea_goods`.`created` AS `created`,`vip_tulin`.`pea_goods`.`updated_by` AS `updated_by`,`vip_tulin`.`pea_goods`.`updated` AS `updated`,`vip_tulin`.`pea_goods`.`ad_client_id` AS `ad_client_id` from `vip_tulin`.`pea_goods` where (`vip_tulin`.`pea_goods`.`pea_customer_id` = 190919175230001)

columna de identificación

carné de identidad seleccione tipo mesa particiones tipo possible_keys llave key_len árbitro filas filtrado Extra
1 SENCILLO pea_goods TODOS 50 10.00 Utilizando dónde
  id 列的编号是select 的序列号,有几个select 就有几个id,并且顺序是按照select 顺序增长的。
  id 越大执行优先级越高,id 相同从上往下执行,id 为null 最后执行。

2. SELECT_TYPE 列

la simple : representa la consulta simple consulta no incluye sub-consultas y de unión
primaria : la más externa consultas de selección complejo
subconsulta : cláusula select subconsulta
deriva : desde cláusula subconsulta

SQL:

set session optimizer_switch='derived_merge=off'; 
-- 关闭 mysql 5.7 新特性对衍生表的合并优化
EXPLAIN SELECT
	( SELECT 1 FROM pea_goods WHERE pea_goods_id = 190919182516001 ) 
FROM
	( SELECT * FROM pea_customer WHERE pea_customer_id = 190919175230001 ) goods

Comparación de la primaria, subconsulta y tipos derivados >> salida:

carné de identidad seleccione tipo mesa particiones tipo possible_keys llave key_len árbitro filas filtrado Extra
1 PRIMARIO sistema 1 100.00
3 DERIVADO pea_customer const PRIMARIO PRIMARIO 8 const 1 100.00
2 subconsulta pea_goods const PRIMARIO PRIMARIO 8 const 1 100.00

Unión : seleccionar la segunda y la posterior unión de la

salida:

carné de identidad seleccione tipo mesa particiones tipo possible_keys llave key_len árbitro filas filtrado Extra
1 PRIMARIO No hay tablas utilizadas
1 UNIÓN

3. columna de la tabla

Esta columna representa xeplain fila está accediendo a la tabla.
desde cuando hay sub-consultas, columna de la tabla consulta actual indica consulta id = N-dependiente, por lo que la primera ID de ejecución de consulta = N
cuando hay unión, unión Resultado Los valores de columna de tabla <unión 1,2> 1 y 2 muestran la participación de la unión y seleccione ID.

4. columna de tipo de

Esta columna muestra el tipo de asociación o de tipo de acceso es MySQL deciden cómo encontrar filas de la tabla, encuentre el intervalo aproximado de filas de datos.
De mejor a peor sistema> const> eq_ref> ref> rangge> Índice> ALL En general: tienen que asegurarse de que la consulta alcanza el rango de nivel, preferiblemente hasta ref

NULL : MySQL puede consultar en la etapa de optimización, no tienen acceso o el índice durante la fase de implementación.

const, Sistema : MySQL puede ser optimizado para una parte de la consulta y la convierte en una constante
(mostrar aviso) cuando se compara con todas las columnas y una clave principal constante o una clave única para la tabla de manera que a lo sumo una fila coincidente, leído una vez , más rápido. sistema de const es un caso especial. Cuando sólo hay una lista de coincidencias tuplas sistema con nombre.

5. possible_keys 列

Esta columna muestra pueden utilizar el índice para encontrar a los
que puede producirse cuando existe explicar possible_keys columnas y tecla de pantalla para NULL, ya que esta situación no es muy datos de la tabla, MySQL pensar en pequeño índice de ayuda en esta consulta, seleccionar toda la tabla investigación

Si la columna es NULL, hay un índice relevante. En este caso, se puede ver si se puede crear un índice apropiado para mejorar el rendimiento de consulta, a continuación, explicar a ver los resultados mediante la comprobación de la cláusula where

6 columna de clave

Esto demuestra columna que MySQL índice hayan usado efectivamente para optimizar el acceso a la tabla,
si el índice no se utiliza como NULL, si quiere cumplir o ignorar índice possible_key columna, el uso force_index, ignore_index en la consulta.

7.key_len 列

Esto demuestra la columna del número de bytes utilizados en el mysql índice, se pueden calcular por el número de columnas que índice específico.

pea_goods_Id tipo bigint y es de 8 bytes.

Primaria consulta clave:

explain select * from pea_goods where pea_goods_Id=190919181614003;

salida

carné de identidad seleccione tipo mesa particiones tipo possible_keys llave key_len árbitro filas filtrado Extra
1 SENCILLO pea_goods const PRIMARIO PRIMARIO 8 const 1 100.00

key_len reglas de cálculo siguiente:

cadena
  • char (n): n longitud de bytes
  • varchar (n): 2-byte de almacenamiento de longitud de la cadena, si es UTF-8, entonces la longitud 3n + 2
tipos numéricos
  • tinyint: 1 byte
  • smallint: 2 bytes
  • INT: 4 bytes
  • bigint: 8 bytes
Hora
  • Fecha: 3 bytes
  • marca de tiempo: 4 bytes
  • fecha y hora: campo de 8 bytes permite Si es NULL, la necesidad de registro es de byte nulo en 1

8 ref columna

Esta columna muestra las columnas de clave de índice de registros en los valores o constantes de columna una tabla de búsqueda utilizados en común son: const (constante), nombres de campo (ejemplo: film.id )

9 filas columnas

Esta columna es para ser leído y MySQL estimar el número de filas de detección, nota que este no es el número de filas del conjunto de resultados

10 columna extra

Esta columna muestra información adicional, consulte la siguiente común importante

  • Índice del Uso : El uso de un índice que cubre

  • Donde el uso de : Uso en declaración a los resultados, las columnas no indexadas cubre la consulta

  • Índice Condition el uso de : la columna de la consulta no está completamente cubierta por el índice, donde las condiciones son una serie de columna que conduce.

  • El temporal del Uso : MySQL necesita para crear una tabla temporal para procesar la consulta, esta situación es por lo general a ser optimizado, el primer pensamiento de utilizar el índice de optimizar.

    1. goods_name ningún índice en este momento para crear una tabla temporal

    EXPLICAR goods_name SELECT DISTINCT de pea_goods

No hay resultados de indexación

carné de identidad seleccione tipo mesa particiones tipo possible_keys llave key_len árbitro filas filtrado Extra
1 PRIMARIO pea_goods ALL Using temporary
EXPLAIN SELECT DISTINCT  goods_name from  pea_goods

有索引结果

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY pea_goods ALL Using index
  • Using filesort

将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的

  1. goods_name 未创建索引,pea_goods,保存排序关键字pea_goods和对应的id,然后排序pea_goods并检索行记录
    EXPLAIN SELECT * from pea_goods ORDER BY goods_name
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY pea_goods ALL Using filesort
  1. goods_name 创建索引
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY pea_goods ALL Using index
  • Select tables optimized away

使用某些聚合函数(比如 max、min)来访问存在索引的某个字段是
EXPLAIN SELECT min(pea_goods_id) from pea_goods ORDER BY goods_name

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE Select tables optimized away

索引最佳实践

创建表

CREATE TABLE `employees` ( 
`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,     
`name` VARCHAR ( 24 ) NOT NULL DEFAULT '' COMMENT '姓名',   
`age` INT ( 11 ) NOT NULL DEFAULT '0' COMMENT '年龄',   
`position` VARCHAR ( 20 ) NOT NULL DEFAULT '' COMMENT'职位',
`hire_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',  
PRIMARY KEY ( `id` ), KEY `idx_name_age_position` ( `name`, `age`, `position` ) USING BTREE  )    
ENGINE = INNODB AUTO_INCREMENT = 4 DEFAULT
CHARSET = utf8 COMMENT = '员工记录表'; 
    
INSERT INTO employees ( NAME, age, position, hire_time ) VALUES ( 'LiLei',22,'manager',NOW());
INSERT INTO employees ( NAME, age, position, hire_time ) VALUES ('HanMeimei', 23, 'dev', NOW()); 
INSERT INTO employees ( NAME, age, position, hire_time ) VALUES ('Lucy',23,  'dev', NOW());

1.全值匹配

1. EXPLAIN SELECT *  FROM     employees  WHERE     NAME = 'LiLei'; 
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE employees ref idx_name_age_position idx_name_age_position 74 const 1
EXPLAIN SELECT     *  FROM     employees  WHERE
NAME = 'LiLei'      AND age = 22; 
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE employees ref idx_name_age_position idx_name_age_position 78 const,const 1
EXPLAIN SELECT     *  FROM     employees  WHERE     NAME = 'LiLei' AND age = 22
ANDposition = 'manager'; 
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE employees ref idx_name_age_position idx_name_age_position 140 const,const,const 1

2.最左前缀法则

如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。

EXPLAIN SELECT * FROM employees WHERE age = 22 AND position ='manager';

结果

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE employees 3 33.33 Using where
EXPLAIN SELECT * FROM employees WHERE position = 'manager';

结果

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE employees 3 33.33 Using where
EXPLAIN SELECT * FROM employees WHERE name = 'LiLei';

结果

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE employees ref idx_name_age_position idx_name_age_position 74 const 1 100.00

3.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描

EXPLAIN SELECT * FROM employees WHERE name ='LiLei';EXPLAIN SELECT * FROM employees    
WHERE left(name,3) = 'LiLei';

结果

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE employees ref idx_name_age_position idx_name_age_position 74 const 1 100.00

给hire_time增加一个普通索引:

   ALTER TABLE `employees`2ADD INDEX `idx_hire_time` (`hire_time`) USING BTREE ; 
    EXPLAIN  select * from employees where date(hire_time) ='2018-09-30';

结果

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE employees 3 100.00 Using where

转化为日期范围查询,会走索引:

EXPLAIN  select * from employees where hire_time >='2018-09-30 00:00:00'  
andhire_time <='2018-09-30 23:59:59';

还原最初索引状态

ALTER TABLE `employees` DROP INDEX `idx_hire_time`;

4.存储引擎不能使用索引中范围条件右边的列

EXPLAIN SELECT * FROM employees WHERE name= 'LiLei' AND age = 22 AND position ='manager';
EXPLAIN SELECT * FROM employees WHERE name= 'LiLei' AND age > 22 AND position ='manager';

5. 尽量使用覆盖索引(只访问索引的查询(索引列包含查询列)),减少select *语句

EXPLAIN SELECT name,age FROM employees WHERE name= 'LiLei' AND age = 23 AND position ='manager';
EXPLAIN SELECT * FROM employees WHERE name= 'LiLei' AND age = 23 AND position ='manager';

6. mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描

EXPLAIN SELECT * FROM employees WHERE name != 'LiLei';

7. is null,is not null 也无法使用索引

EXPLAIN SELECT * FROM employees WHERE name is null

8. like以通配符开头('$abc...')mysql索引失效会变成全表扫描操作

EXPLAIN SELECT * FROM employees WHERE name like '%Lei' 
EXPLAIN SELECT * FROM employees WHERE name like 'Lei%'
问题:解决like'%字符串%'索引不被使用的方法?

a)使用覆盖索引,查询字段必须是建立覆盖索引字段

    EXPLAIN SELECT name,age,position FROM employees WHERE name like '%Lei%';

b)如果不能使用覆盖索引则可能需要借助搜索引擎

9.字符串不加单引号索引失效

EXPLAIN SELECT * FROM employees WHERE name = '1000';
EXPLAIN SELECT * FROM employees WHERE name = 1000;

10.少用or或in

用它查询时,mysql不一定使用索引,mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引,详见范围查询优化

EXPLAIN SELECT * FROM employees WHERE name = 'LiLei' or name = 'HanMeimei';

11.范围查询优化给年龄添加单值索引

ALTER TABLE `employees`2ADD INDEX `idx_age` (`age`) USING BTREE ;
explain select * from employees where age >=1 and age <=2000;

没走索引原因:mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引。比如这个例子,可能是由于单次数据量查询过大导致优化器最终选择不走索引优化方法:可以讲大的范围拆分成多个小范围

explain select * from employees where age >=1 and age <=1000;
explain select * from employees where age >=1001 and age <=2000;

还原最初索引状态

1ALTER TABLE employees2DROP INDEX idx_age;

索引使用总结:

假设 index(a,b,c)

where 语句 索引是否被使用
where a=3 Y ,使用到a
where a =3 and b =4 Y ,使用到 a,b
where a =3 and b =4 and c=5 Y ,使用到 a,b,c
where b=3 / where b= 3 and c=4 /where c=5 N
where a=3 and c=5 使用到a ,但是c不可以, b中间断了
where a=3 and b like 'KK%' and c=4 Y ,使用到a,b,c
where a=3 and b like '%KK' and c =4 Y 只用到a
where a =3 and b like '%KK%' and c=4 Y 只用到a
where a =3 and b like 'K%KK%' and c=4 Y 用到a,b,c

like KK%相当于=常量,%KK和%KK% 相当于范围

Supongo que te gusta

Origin www.cnblogs.com/wxs121/p/12550107.html
Recomendado
Clasificación