最近发现数据库sql优化对客户的体验有很大的提高。在项目中将之前的DBUtils+反射来查询的方式改变为Spring Template。效率升高了很多。因此,觉得有必要对数据库查询优化做一个总结。
1.根据实际情况创建数据库索引
在经常需要的字段创建索引,比如经常用到的name, id, date等字段。具体的情况根据业务确定。也可以在多个字段上创建索引
2.使用预编译查询
一般的后台程序是根据用户的输入执行动态SQL,这时候可能有SQL注入漏洞攻击。所以,一般要求对SQL进行预编译,并且第一次执行的时候DBMS会对其进行语句查询优化并且预编译。这样执行SQL的时候就直接使用预编译结果,提高执行的速度。
3.调整Where语句中的连接顺序
DBMS一般采用自下而上的的顺序解析Where字句,根据这个原理表连接最好写在其他where条件之前。并且那些过滤掉最大数量记录的条件必须写在Where子句的末尾
4.尽量将多条SQL语句压缩到一条SQL
每次执行SQL的时候都要建立网络连接,进行权限校验,进行SQL语句查询优化、发送执行结果,这个过程非常耗时,所以一般业务可行的条件下压缩多条语句到一条SQL语句中
5.用Where替换having
不要使用having,having只会在检索出所有记录之后才会对结果集进行过滤,而where实在聚合之前。having一般用于聚合函数
6.使用表的别名
当在SQL语句中连接多个表时,请用表的别名,并且把别名前缀到每个列名上,可以减少解析时间,避免发生列名歧义引起的错误
7.in 和 exists 一般情况下使用exists,因为in不走索引
8.避免在索引上使用计算
在where子句中,如果索引是函数的一部分,DBMS的优化器将不会使用索引而使用全表查询。
// 效率低:
select * from person where salary*12>25000(salary是索引列)
// 效率高:
select * from person where salary>25000/12(salary是索引列)
9.用 union all 替换 union
当SQL语句需要union两个查询结果时,一般使用union all。
union和union all的差别就在于union会对数据做一个distanct的动作,而这个distanct动作的速度则取决于现有数据的数量,数量越大则时间也越慢。而对于几个数据集,要确保数据集之间的数据互相不重复,基本是O(n)的算法复杂度。
UNION还有一个用处,我们在海量数据的查询中,如果使用
select * from c_cons where cons_id in ('691339365','3387785','3387954');
这样的查询语句,会引起全表扫描,可以使用UNION ALL来代替,如:
select * from c_cons where cons_id='691339365'
UNION ALL
select * from c_cons where cons_id='3387785'
UNION ALL
select * from c_cons where cons_id='3387954'
这样查询比使用in查询要快很多,它不会去进行全表扫描。
10.避免SQL中出现隐式类型转换
当一张表中索引字段在作为where条件的时候,如果进行了隐式类型转化,则此索引字段将不会被识别,因为隐式类型也属于计算,索引将会采用全表扫描。
11.防止检索范围过宽
使用is not null 或者不等于判断,可能造成优化器假设匹配的记录数太多
使用立刻运算符的时候, “a%” 将会使用索引, 而”%a”和”%ac”则会使用全表扫面,因此”%a”和”%ac”尽量不要使用