SQL性能优化
SQL性能优化
前言
SQL优化是一个长期的过程。很多优化原则并不是固定不变的,应根据实际业务要求进行。管理员应经常检查TOP SQL,及时与开发人员进行沟通,根据实际情况制定优化策略。原则上讲,SQL优化是应用开发人员的事。
第1条
SQL语句多表关联时,应使用别名。相关字段通过别名进行应用。使用别名可以减少优化器查找对象关联的复杂度,降低解析代价。
第2条
对于关键SQL语句,尽量简化,不要包含太多的层次,避免执行计划错误的可能,原则上不能超过5层;
第3条
应尽可能避免order by,group by,distinct等引起不必要排序的操作。
第4条
应尽量使检索条件的两侧类型一致,避免where查询条件做隐型转换时后出现混乱,导致产生错误的执行计划。
第5条
注意like的使用方法,变量%要注意查询范围, %在开头或者末尾,选择性最好。
第6条
防止group by的key分布不均匀,在SQL执行前设置防倾斜的参数:
set hive.groupby.skewindata=true。
有数据倾斜的时候进行负载均衡,当选项设定为true,生成的查询计划会有两个MR Job。第一个MR Job中,Map 的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MR Job再根据预处理的数据结果按照Key分布到Reduce中(这个过程可以保证相同的Key被分布到同一个Reduce中),最后完成最终的聚合操作。
当group by‘常量’时,该设置无效。
第7条
join时key分布不均匀会导致数据倾斜,可以有两种解决方案:
1.如果join的两边有一个是小表,可以把join改成map join来处理。
2.倾斜的key用单独的逻辑来处理,例如经常发生两边的key里有大量null数据导致了倾斜。则需要在join前先过滤掉null的数据或者补上随机数,然后再进行join。
如:
select * from log a
left outer join users b
on case when a.user_id is null then concat('hive',rand()) else a.user_id end = b.user_id;
如果key为null的数据不需要使用建议先过滤掉key值为null的数据,当然大部分情况下,可能倾斜的值不是null,而是有意义的数据,那么这时候就需要把这类数据单独拎出来单独处理,分而治之。
第8条
count distinct时也容易发生数据倾斜,常见于固定的特殊值较多的场景。count distinct时,将值为空的情况单独处理,如果只是计算count distinct,可以不用处理,直接过滤,在最后结果中加1。如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理,再和其他计算结果进行union。
第9条
当一个大表和一个或多个小表做JOIN时,要求使用MAPJOIN,性能比普通的JOIN要快很多。 另外,MAPJOIN 还能解决数据倾斜的问题。
-
LEFT OUTER JOIN的左表必须是大表
-
RIGHT OUTER JOIN的右表必须是大表
-
FULL OUTER JOIN不能使用MAPJOIN
-
MAPJOIN支持小表为子查询
-
使用MAPJOIN时需要引用小表或是子查询时,需要引用别名
数据倾斜
数据倾斜原因:
1.key分布不均匀
2.业务数据本身的特性
3.建表时考虑不周
4.某些Sql语句本身就有数据倾斜
(目的是如何将数据均匀的分配到各个reduce中)
处理数据倾斜主要的方法:
1.map join
2.map端combine
3.给key赋前缀进行扩容
4.避免使用造成单reduce的函数