mysql 查询优化器有几个目标,但是其中最主要的目标是尽可能地使用索引,并且使用最严格的索引来消除尽可能多的数据行。最终目标是提交 select语句查找数据行,而不是排除数据行。优化器试图排除数据行的原因在于它排除数据行的速度越快,那么找到与条件匹配的数据行也就越快。如果能够首先进行最严格的测试,查询就可以执行地更快。
explain的每个输出行提供一个表的相关信息,并且每个行包括下面的列:
项 说明Using temporary 表示 MySQL 在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。
下面是简单几个例子,100w行数据测试
explain SELECT * FROM `ih_user` WHERE 1 limit 800000,10
查询花费 5.1838 秒
SELECT * FROM `ih_user` WHERE 1 limit 800000,10
优化为
查询花费 0.2838 秒
SELECT id,username FROM `ih_user` WHERE 1 limit 800000,10
再优化为:
查询花费 0.1838 秒
SELECT id,username FROM `ih_user` WHERE id in(800001,800002,800003,800004,800005,800006,800007,800008,800009,800010);
再优化为:
查询花费 0.0009 秒
SELECT id,username FROM `ih_user` WHERE id BETWEEN 800001 and 800010
查询花费 4.8235 秒
SELECT id,username FROM `ih_user` WHERE username like '%陈道明%'
查询花费 2.3432 秒
SELECT id,username FROM `ih_user` WHERE username like '陈道明%'
优化为 username加了索引
查询花费 0.0012 秒
SELECT id,username FROM `ih_user` WHERE username like '陈道明%'
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ih_user_temp range username username 767 NULL 18 Using where
order by优化
explain SELECT id,username,regtime FROM `ih_user_temp` WHERE id>800001 order by regtime desc limit 10
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ih_user_temp range PRIMARY PRIMARY 4 NULL 162865 Using where; Using filesor
order by字段使用索引或者前面查询出来的字段是索引
explain SELECT id,username,regtime FROM `ih_user_temp` WHERE id>800001 order by id desc limit 10
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ih_user_temp range PRIMARY PRIMARY 4 NULL 162865 Using where
update优化
update的字段加索引
影响了 5 行。 ( 查询花费 4.2672 秒 )
update `ih_user_temp` set sex=0 where mobile='18250617881'
影响了 5 行。 ( 查询花费 0.0011 秒 )
update `ih_user_temp` set sex=0 where username='陈道明'
update `ih_user_temp` set sex=0 where mobile='18250617881'
组合索引
ALTER TABLE `ih_user_temp` ADD INDEX sex_city_age( `sex` , `city` , `age` ) ;
#修改索引名 其实就是先删除之前的索引再新增索引
ALTER TABLE `big`.`ih_user_temp` DROP INDEX `sex` ,
ADD INDEX `sex_city_age` ( `sex` , `city` , `age` )
explain SELECT * FROM `ih_user_temp` WHERE city='上海' and age=20
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ih_user_temp ALL NULL NULL NULL NULL 999921 Using where
explain SELECT * FROM `ih_user_temp` WHERE sex=1 and age=20
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ih_user_temp ALL sex_city_age NULL NULL NULL 999921 Using where
优化为
explain SELECT * FROM `ih_user_temp` WHERE sex=1 and city='上海' and age=20
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ih_user_temp ref sex_city_age sex_city_age 64 const,const,const 112 Using where
例子2
如果查询的字段索引未覆盖,mysql会自动全表扫描(这样会更快),不需索引查然后再回表
explain SELECT * FROM `ih_user_temp` WHERE sex=1
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ih_user_temp ref sex_city_age sex_city_age 1 const 4386
优化为 查询的字段是索引中的
explain SELECT sex FROM `ih_user_temp` WHERE sex=1
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ih_user_temp ref sex_city_age sex_city_age 1 const 4386
group by 优化
#group by和order by可能会让cpu占用很高
显示行 0 - 9 (10 总计, 查询花费 65.4372 秒)
SELECT count(*) num,city FROM `ih_user_temp` where city in (select city from ih_user_temp where city='上海' limit 100) group by username order by num desc limit 10;