1、SQL的执行顺序
2、基础的SQL优化
2.1、查询SQL尽量不要使用select *,而是具体到字段
2.2、避免在where子句中使用or来连接条件
2.3、使用varchar代替char
2.4、尽量使用数值代替字符串类型
2.5、查询尽量避免返回大量的数据
2.6、使用explain查看SQL语句的执行计划
2.7、是否使用了索引及其扫描类型
2.8、创建name字段的索引
2.9、优化like语句
2.10、字符串怪现象
2.11、索引不宜过多,一般在五个以内即可
2.12、索引不适合建在有大量重复数据的字段上
2.13、where限定查询的数据
2.14、避免在索引上使用内置函数
2.15、避免在where子句中使用表达式操作和!=后<>操作符
2.16、去重distinct过滤字段要少
2.17、where中使用默认值代替null
3、高级SQL优化
3.1、批量插入使得性能提升
3.2、批量删除优化
3.3、提高group by语句的效率
3.4、符合索引最左原则
3.5、排序字段创建索引
3.6、删除冗余和重复的索引
3.7、不要有超过5个以上的表的连接
3.8、inner join left join right join 优先考虑inner join
3.9、in 子查询的优化
3.10、尽量使用union all 代替union
解释:
字段过多时一个表可以达到100多个字段甚至跟多,所以我们只需要取自己想要的字段,节省资源,减少网络开销
select * 进行查询时可能不会用到索引而走全表扫描
解释: 查询ID为1或者薪水为5000的用户
反例:select * from student where ID=1 or salary =5000;
正例(使用union all):select * from student where ID=1 union all
select * from student where salary =5000;
使用or很有可能会使索引失效,从而走全表扫描(or不确定性)
解释: varchar会按照内存的实际长度存储,存储空间小,可以节省存储空间
char 按照声明大小存储,不足的补空格
其次对于查询来说在一个相对较小的字段内搜索效率更高
解释:主键(id) primary key有限考虑使用数值类型的int
性别(sex)0代表女,1代表男,数据库没有布尔类型,MySQL推荐使用tinyint
支付方式(payment)1代表现金,2代表微信,3代表支付宝,4代表信用卡
服务状态 1代表开启,2代表暂停,3代表停止
商品状态 1代表上架,2代表下架,3代表删除
解释:如果查询返回的数据量很大就会造成查询时间过长,网络传输的时间过长,通常采用分页方式,一页习惯10/20/30条
解释:explain主要看SQL是否使用了索引
解释;system(只有一条记录)>const(针对主键或唯一建)> eq_ref(使用唯一索引)>ref(使用非唯一索引)>range(索引范围扫描)>index(索引全扫描)>all(全表扫描)
解释: alter table student add index index_name(Name);
解释: 反例:explain select id,name from student where name like '%1';
正例:explain select id,name from student where name like '1%';
解释:未能正确的使用索引,
name=123(不会走索引,类型不匹配,MySQL会做隐式类型转换)
name ='123'(会走索引)
解释:索引过多会降低插入和更新的效率
解释:比如sex字段,SQL优化器是根据表中的数据量来优化的,如果索引列还有大量的重复数据,MySQL查询优化器推算发现不走索引的成本更低,很可能就不走索引了
解释:表中就只有一个男的
反例:select id,name from student where sex='男'
正例:select id,name from student where id=1 and sex='男';
解释:反例:explain select * from student where id+1-1=+1;
正例:explain select *from student where id = 1=1-1;
使用 !=后<>操作符很有可能会使索引失效
解释:insert 语句时避免一条一条的插入,可以一次性插入想要的语句
默认新增SQL有事务控制,导致每条都需要开启事务和提交事务,而批量处理只需一次事务的开启和提交,从而提高速度
解释:避免同时修改或删除过多的数据,因为会造成CPU利用率过高,造成锁表的操作
反例:delete from student where id<100000;
for(User user:list){
delete from student;
}
正例:delete from student where id between 500 and 1000;
for(User user:list){
delete from student where id <500;
}
解释:可以考虑先过滤在分组(其实时where和having的区别)
where在group by 之前使用
having在group by之后使用,而且having过滤的一般是组合函数(count,avg,min,max,sum)
解释:创建复合索引
alter table student add index index_name_saraly(name,saraly)
1.满足复合索引的左侧顺序,哪怕只是一部分,索引生效
select * from student where name='name1';
2.没有满足最左原则,索引失效
select * from student where saraly =3000;
3,复合索引全使用
select * from student where name='name1' and saraly=3000;
select * from student where saraly=3000 and name='name1';(虽然违背了最左原则,但MySQL会进行优化)
解释:什么样的字段才需要创建索引呢,原则就是where和order by中常用的字段就创建索引
解释:show index from student
创建索引:alter table student add index index_name(name);
删除student表的index_name索引:drop index index_name on student;
alter table student drop index index_name;
解释:union和unionall的区别是,union会自动去掉多个结果集合中的重复结果,而union all则将所有的结果全部显示出来,不管是不是重复
union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序 union在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION