CREATE TABLE employees ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(24) NOT NULLDEFAULT'' COMMENT '姓名', age int(11) NOT NULLDEFAULT'0' COMMENT '年龄', position varchar(20) NOT NULLDEFAULT'' COMMENT '职位', hire_time timestampNOT NULLDEFAULTCURRENT_TIMESTAMP COMMENT '入职时间', PRIMARY KEY (id), KEY idx_name_age_position (name,age,position) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1DEFAULT CHARSET=utf8 COMMENT='员工记录表';
mysql> EXPLAIN SELECT*FROM employees force index(idx_name_age_position) WHERE name >'Artisan'AND age =22AND position ='manager'; +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+-----------------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+-----------------------+ |1| SIMPLE | employees |NULL|range| idx_name_age_position | idx_name_age_position |74|NULL|50087|1|Using index condition| +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+-----------------------+ 1rowinset
优化二 覆盖索引优化
1 2 3 4 5 6 7 8 9
mysql> EXPLAIN SELECT name , age , position FROM employees WHERE name >'Artisan'AND age =22AND position ='manager'; +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+--------------------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+--------------------------+ |1| SIMPLE | employees |NULL|range| idx_name_age_position | idx_name_age_position |74|NULL|50087|1|Usingwhere; Using index | +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+-------+----------+--------------------------+ 1rowinset
mysql>
name , age , position 是联合索引,在索引树上,同时索引树上的叶子节点还会关联一个主键id , 如果查询 * 的话,还要根据id去主键索引上去查找其他字段,需要回表, 如果仅查询二级索引树idx_name_age_position上的字段,那就无需回表操作了,效率自然高一些。
Case 2 : in和or在表数据量比较大的情况会走索引,在表记录不多的情况下会选择全表扫描
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
mysql> EXPLAIN SELECT*FROM employees WHERE name in ('LiLei','HanMeimei','Lucy') AND age =22AND position ='manager'; +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+ |1| SIMPLE | employees |NULL|range| idx_name_age_position | idx_name_age_position |140|NULL|3|100|Using index condition| +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+ 1rowinset
mysql> EXPLAIN SELECT*FROM employees WHERE (name ='LiLei'or name ='HanMeimei') AND age =22AND position ='manager'; +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+ |1| SIMPLE | employees |NULL|range| idx_name_age_position | idx_name_age_position |140|NULL|2|100|Using index condition| +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+ 1rowinset
再搞个小表 ,和 employees 一模一样哈,连索引也得一样,插入3条数据 。
1 2 3 4 5 6 7 8 9 10 11 12 13
CREATE TABLE employees_2 ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(24) NOT NULLDEFAULT'' COMMENT '姓名', age int(11) NOT NULLDEFAULT'0' COMMENT '年龄', position varchar(20) NOT NULLDEFAULT'' COMMENT '职位', hire_time timestampNOT NULLDEFAULTCURRENT_TIMESTAMP COMMENT '入职时间', PRIMARY KEY (id), KEY idx_name_age_position (name,age,position) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1DEFAULT CHARSET=utf8 COMMENT='员工记录表';
INSERT INTO employees_2(name,age,position,hire_time) VALUES('LiLei',22,'manager',NOW()); INSERT INTO employees_2(name,age,position,hire_time) VALUES('HanMeimei', 23,'dev',NOW()); INSERT INTO employees_2(name,age,position,hire_time) VALUES('Lucy',23,'dev',NOW());
1 2 3 4 5 6 7 8 9
mysql> EXPLAIN SELECT*FROM employees_2 WHERE name in ('LiLei','HanMeimei','Lucy') AND age =22AND position ='manager'; +----+-------------+-------------+------------+------+-----------------------+------+---------+------+------+----------+-------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-------------+------------+------+-----------------------+------+---------+------+------+----------+-------------+ |1| SIMPLE | employees_2 |NULL|ALL| idx_name_age_position |NULL|NULL|NULL|3|100|Usingwhere| +----+-------------+-------------+------------+------+-----------------------+------+---------+------+------+----------+-------------+ 1rowinset