1、建表
CREATE TABLE `person` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`job1` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`job2` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`job3` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `ind_123` (`job1`,`job2`,`job3`) USING BTREE
) ENGINE=InnoDB;
2、插入数据
INSERT INTO `person` (`id`, `name`, `job1`, `job2`, `job3`) VALUES ('1', '1', '1', '1', '1');
INSERT INTO `person` (`id`, `name`, `job1`, `job2`, `job3`) VALUES ('2', '2', '2', '2', '2');
INSERT INTO `person` (`id`, `name`, `job1`, `job2`, `job3`) VALUES ('3', '3', '3', '3', '3');
可以从两方面来回答
1、索引树的问题,底层原理机制
1、如下表,建立了2个索引,那就就有两颗索引树,因为innodb是聚集索引,那么主键id就是聚集索引,ind_123就是二级索引
查询数据的时候,如果
Select * from person where job2="2",通过explain可以看到,并没有使用索引
但是如果使用
SELECT
job1,
job2,job3
FROM
person
WHERE
job2 = "2"
通过explain可以看到,使用了
ind_123索引,并且key_len长度为458,因为创建表的时候varchar字段都是用的utf-8,同时字段是允许为null的所以就是50*3+2+1=153 153*3=459 所以使用的是ind_123这个索引表的全表扫描,避免了回表操作
但是如果使用
EXPLAIN SELECT
job1,
job2,
job3
FROM
person
WHERE
job1 = '1'
AND job2 = '2'
通过explain可以看到,使用了
ind_123索引,并且key_len长度为306,因为创建表的时候varchar字段都是用的utf-8,同时字段是允许为null的所以就是50*3+2+1=153 153*2=306
所以使用的是ind_123这个索引表的索引扫描,并且索引类型用的是ref相比较index更快,原理就是指需要扫描出二级索引树中的部分数据,因为job1和job2的数据是确定了的!查询效率相比较之前的全表索引树扫描会更加快,避免了回表操作!
所以,不能用*来笼统的作为查询条件,这里是有很大的优化空间的!
2、连接查询时,* 无法进入缓冲池
使用select * 放一些无用的列,只会白白的占用缓冲空间。浪费本可以提高性能的机会。