SQL优化,老司机才懂得的处理技巧(2)
我们接着上一篇继续
用连接查询代替子查询
-
mysql中如果需要从两张表中查询出数据的话,一般有两种方式:子查询和连接查询,子查询如下:
-
select * from order where id in(select * from user where status = 1);
-
子查询语句可以通过in关键字实现,一个查询语句的条件落在另一个select语句的查询结果中。程序先运行嵌套在最内层的语句,在运行外层的语句,子查询语句的优点是简单,结构化,如果涉及的表不多的情况下我们是可以使用这种方式的,但是子查询需要创建临时表,查询完毕后,需要再进行删除临时表,有一些额外的性能消耗,这时候我们可以改成连接查询
-
select * from order inner join user on o.id = u.id and status = 1;
join的表不宜过多
- 根据阿里巴巴开发者手册的规定,join表的数量不应该超过三个,如果join的表太多,mysql在选择索引的时候会非常复杂,很容易选择错误,如果没有命中索引,那么会非常的慢,我们应该尽量减少join表的数量
- 如果在实际的业务场景中没有办法避免过多的join表的数量,那就搞
join时要注意
-
我们涉及到多张表联合查询的时候,一般会使用join关键字,而使用最好的是left join和inner join
-
left join,在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录
-
right join,在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录
-
inner join(内连接),在两张表进行连接查询时,只保留两张表中完全匹配的结果集
控制索引的数量
- 众所周知,索引能够显著的提升查询sql的性能,但是索引数量并不是越多越好,因为表中新增数据时,需要同时为他创建索引,而索引是需要额外的存储空间的,而且还会有一定的性能消耗
- 阿里巴巴在开发手册中规定,索引的数量最好不要超过5个,MySQL使用b+树保存索引的,在进行增删改的时候,会有额外的性能消耗
- 如果表中需要的索引数量超过5个怎么办呢?
- 我们就能建立联合索引就不建立单个索引,可以删除无用索引,如果数据量超级大,我们就进行考虑不使用mysql,可以使用hbase
选择合理的字段类型
-
char表示固定字符串类型,该类型的字段存储空间的固定的,会浪费存储空间
-
alter table order add column code char(20) not null;
-
varchar表示变长字符串类型,该类型的字段存储空间会根据实际数据的长度调整,不会浪费存储空间
-
alter table order add column code varchar(20) not null;
-
如果长度固定的字段,比如用户的手机号们一般都是11位的,那么我们直接定义为11位就可以了,但是如果是备注这样的字段我们就不能使用char,会浪费大量的空间,我们应该使用varchar
-
我们在选择类型的时候,应该遵循这样的原则:
- 能用数字类型,就不用字符串类型,因为字符串处理会比数字慢
- 尽可能使用小的类型
- 长度固定的类型,如char类型
- 长度可变的字符串类型,如varchar类型
- 金额要使用decimal,避免精度的丢失
提升group by的效率
-
我们有很多场景都会使用group by关键字,它主要的功能是去重和分组,通常会和having一起使用,表示分组之后再根据一定的条件过滤数据,举个反例:
-
select * from order group by id having id < 200;
-
这种写法性能不好,他先把所有的数据都查出来之后在进行分组,再去过滤用户id小于200的用户,分组是一个相对耗时的操作,为什么我们不能先进行缩小范围呢?
-
select * from order where id < 200 group by id ;
-
在分组之前我们使用where条件进行过滤,把多余的数据过滤掉,这样分组的效率就会变高,我们在做耗时的事情之前,尽可能把数据范围进行缩小
索引优化
- sql优化中,有一个非常重要的内容就是:索引优化
- 很多时候,我们的sql语句,走了索引和没有走索引,执行效率差别很大,索引索引优化被作为sql优化的首选
sql优化
-
检查sql语句有没有走索引
-
explain select * from order where id < 200 group by id ;
-
通过explain关键字我们就可以看出sql到底有没有走索引,然后关于explain问题大家上网搜一下,有时间在讲解