一文读懂 MySQL 索引( 五 )

一文读懂 MySQL 索引
文章插图
我们用这个索引来分析,key_len 为 63 是怎么来的?

一文读懂 MySQL 索引

文章插图
创建 user 表的时候,不知道大家有没有注意到,name 的字符集为 utf8
MySQL 5.0 版本以上,utf8 字符集下每个字符占用 3 个字节,varchar(20) 则占用 60 个字节 , 同时因为 varchar 是变长字符串 , 需要额外地字节存放字符长度,共两个字节,此外,name 字段可以为 null 值,null 值单独占用一个字节,加在一起一共 63 个字节
9、ref
当使用索引列等值匹配的条件去执行查询时,也就是在访问方法是consteq_refrefref_or_nullunique_subqueryindex_subquery其中之一时,ref列展示的就是与索引列作等值匹配的具体信息,比如只是一个常数或者是某个列 。
一文读懂 MySQL 索引

文章插图
10、rows
预计需要扫描的函数
11、filtered
filtered 这个是一个百分比的值,表里符合条件的记录数的百分比 。简单点说,这个字段表示存储引擎返回的数据在经过过滤后,剩下满足条件的记录数量的比例 。
12、Extra
Extra是用来说明一些额信息的,从而帮助我们更加准确的理解查询
5.3高性能 的索引使用策略5.3.1 不要在索引列上做任何操作explain select * from user where left(name,2) = '小芳';
一文读懂 MySQL 索引

文章插图
这段 sql 对 name 字段做了函数操作,导致索引失效
5.3.2 最左前缀法则在使用联合索引查询时,应该遵循最左前缀原则 , 指的是查询从索引的最左前列开始并且不跳过索引中的列 。
创建一张 goods 表,有一个联合索引包含了 name,price、mark 三个字段
DROP TABLE IF EXISTS `goods`;CREATE TABLE `goods`(`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`price` int(10) NULL DEFAULT NULL,`mark` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE,INDEX `idx_all`(`name`, `price`, `mark`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of goods-- ----------------------------INSERT INTO `goods` VALUES (1, '手机', 5678, '华为手机');INSERT INTO `goods` VALUES (2, '电脑', 9888, '苹果电脑');INSERT INTO `goods` VALUES (3, '衣服', 199, '好看的衣服');执行下面的查询语句:
explain select * from goods where name = '手机' and price = 5678 and mark = '华为手机';
一文读懂 MySQL 索引

文章插图
从上图可以看到 type 为 ref 。
现在我们不从最左侧开始查询,直接跳过 name 字段
explain select * from goods where price = 5678 and mark = '华为手机';
一文读懂 MySQL 索引

文章插图
type 从 ref 变成了 index,这是因为 MySQL 建立索引时是按照组合索引中的字段顺序来排序的,如果跳过中间某个字段 , 则不一定是有序的了 。
5.3.3 尽量使用覆盖索引覆盖索引,需要查询的字段全部包含在索引列中,不需要回表查询

推荐阅读