Mysql中Explain详解及索引的最佳实践
Mysql中Explain详解及索引的最佳实践
- 1.Explan工具的介绍
- 1.1 Explan 分析示例
- 1.2 Explain中的列
- 1.2.1 id
- 1.2.2 select_type
- 1.2.3 table
- 1.2.4 partitions
- 1.2.5 type
- 1.2.6 possible_keys
- 1.2.7 key
- 1.2.8 key_len
- 1.2.9 ref
- 1.2.10 rows
- 1.2.11 filtered
- 1.2.12 Extra
1.Explan工具的介绍
-
使用EXPLAIN关键字可以模拟优化器执行SQL语句,分析查询语句
-
在 SELECT 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,执行查询会返回执行计划的信息,而不是执行这条SQL
1.1 Explan 分析示例
参考文档:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
--示例表
DROP TABLE IF EXISTS `system_encryption_user`;
CREATE TABLE `system_encryption_user` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',`login_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录名',`email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'email',`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名',`mobilephone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '手机',`phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '固定电话',`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用户密码',`company_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '所属分公司',`dept` int(10) NULL DEFAULT NULL COMMENT '所属部门',`is_delete` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 445 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;INSERT INTO `system_encryption_user` VALUES (1, 'superAdmin', 'Zsxxxxxx@163.com', '超级管理员', '12345678910', '12345678910', '$2a$10$UUZGvFdSju3/kT6H7lMmF.', NULL, 0);DROP TABLE IF EXISTS `system_encryption_role`;
CREATE TABLE `system_encryption_role` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id ',`role_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '角色名称',`role_description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '角色描述',PRIMARY KEY (`id`) USING BTREE,INDEX `index_name`(`role_name`(191)) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;INSERT INTO `system_encryption_role` VALUES (1, 'SUPERADMIN', '超级管理员');DROP TABLE IF EXISTS `system_encryption_user_role`;
CREATE TABLE `system_encryption_user_role` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',`user_id` int(11) NULL DEFAULT NULL COMMENT '用户id',`role_id` int(11) NULL DEFAULT NULL COMMENT '角色id',PRIMARY KEY (`id`) USING BTREE,INDEX `index_user_role`(`user_id`, `role_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 411 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of system_encryption_user_role
-- ----------------------------
INSERT INTO `system_encryption_user_role` VALUES (1, 1, 1);
EXPLAIN SELECT * FROM system_encryption_user WHERE id=1;
1.2 Explain中的列
1.2.1 id
id列的编号是 select 的序列号,有几个 select 就有几个id,并且id的顺序是按 select 出现的顺序增长的。
id列越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行。
1.2.2 select_type
select_type 表示对应的是简单的还是复杂的查询
-
simple 简单查询 查询不包含子查询和union
EXPLAIN SELECT * FROM system_encryption_user WHERE id=1;
-
primary 复杂查询中最外层的SELECT
-
subquery 包含在SELECT 中子查询(不在from子句中)
-
derived 包含在from子句中的子查询 临时表也称为(衍生表或者派生表)
-- 关闭mysql 5.7 版本对衍生表的优化 set session optimizer_switch='derived_merge=off';EXPLAIN SELECT (SELECT 1 FROM system_encryption_user WHERE id=1) FROM (SELECT * FROM system_encryption_user WHERE id=1) exp
-
在 union 中的第二个和随后的 select
-- 恢复 set session optimizer_switch='derived_merge=on'; EXPLAIN SELECT * FROM system_encryption_user UNION ALL SELECT * FROM system_encryption_user
1.2.3 table
表示Explain优化器正在访问哪个表
- 当 from 子句中有子查询时,table列是 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查
询。 - 当有 union 时,UNION RESULT 的 table 列的值为<union1,2>,1和2表示参与 union 的 select 行id。
1.2.4 partitions
如果查询是基于分区表的话,partitions 字段会显示查询将访问的分区。
1.2.5 type
关联类型或访问类型
依次从最优到最差分别为:
system >const>eq_ref>ref>range>index>ALL
- NULL 不需要访问表或索引
EXPLAIN SELECT MIN(id) FROM system_encryption_user_role
- const,system : mysql能对查询的某部分进行优化并将其转化成一个常量用于primary key 或 unique key 的所有列与常数比较时,所以表最多有一个匹配行,读取1次,速度比较快。system是const的特例,表里只有一条元组匹配时为system
EXPLAIN SELECT * FROM (SELECT * FROM system_encryption_user WHERE id=1) tmp;