SQL调优的总结

102 阅读5分钟

SQL调优的总结

一:sql语句调优的基本原则:

“二八原理”是一个普遍的真理,在计算机的世界中表现的更加明显,那就是20%的代码资源占用了80%的总资源消耗。SQL语句也是一种代码,因此它也符合这个原理。在进行SQL语句调优的时候,应该把主要的精力放到这20%最消耗系统资源的SQL语句中,不要想着把所有的SQL语句调整在最优状态。

二:如何调优

1、索引

索引是数据库调优最根本的优化方法。根据索引的顺序与数据表的物理顺序是否相同,可以把索引分成两种类型:聚簇索引(数据表的物理顺序和索引顺序相同)和非聚簇索引(数据表的物理顺序和索引顺序不相同)。他们两者之间的区别,在这里我用字典的目录比喻一下就是聚簇索引是拼音目录,非聚簇索引是偏旁部首目录。还有就是创建聚簇索引时一张表只能有一个,因为表中数据的物理顺序只能有一个,而非聚簇索引则可以创建多个。

由于索引占据一定的空间,而且索引也会降低数据插入、更新、删除的速度,所以应该只创建必要的索引,一般在检索时用的字段创建索引。

索引还会造成存储碎片的问题。当你删除一条记录时,对应的索引项并不会被删除,经过一段时间的增删改操作之后,数据库中就会出现大量的存储碎片,降低数据库的运行速度。如果存储碎片过多,要进行“碎片整理”,最方便的手段就是重建索引。即将先前创建的索引删除然后重新创建索引。主流数据库管理系统都提供了重建索引的功能,比如REINDEX、REBUILD等。

2、使用预编译查询

程序通常根据用户的输入来动态执行SQL语句,这时应该尽量使用参数化SQL,这样不仅可以避免SQL注入漏洞攻击,最重要的是数据库会对这些参数化SQL执行预编译。这样第一次执行的时候DBMS会为这个SQL进行查询优化并且执行预编译,以后再执行这个SQL的时候就直接使用预编译的结果,这样可以大大提高执行的速度。

3、调整WHERE子句中的连接顺序。

DBMS一般采用自下而上的顺序解析WHERE子句,所以表连接最好写在其他WHERE条件之前,那样可以过滤掉最大数量纪录。

4、SELECT语句中避免使用 *

“SELECT *”比较简单,但是除非确实需要检索所有的列,否则会增加网络的负载和服务器的资源消耗。即使确实需要检索所有的列,也不要使用“SELECT ”,因为DBMS会在解析的过程中,把依次转换成所有的列名,意味着耗费更多的时间。

5、尽量将多条SQL压缩到一句SQL中

每次执行SQL的时候都要建立网络连接、进行权限校验、进行SQL语句的查询优化、发送执行结果。这个过程是非常耗时的,因此尽量避免过多的执行SQL语句,能够压缩到一句SQL执行语句就不要多条来执行。

6、用WHERE子句替换HAVING子句

要避免使用HAVING子句,因为HAVING只会检索出所有记录之后才对结果集进行过滤。如果能通过WHERE子句限制纪录的数目,那就能减少这方面的开销。HAVING中的条件一般用于聚合函数的过滤,除此之外,应将条件写在WHERE子句中。

7、使用表的别名

当在SQL语句中有连接多个表时,使用表的别名并把别名前缀置于每个列名上。这样可以减少解析的时间并减少那些由列名歧义引起的语法错误。

8、用EXISTS代替IN

在查询中,为了满足一个条件,往往需要对另一个表进行连接,在这种情况下使用EXISTS而不是使用IN,通常将会提高查询的效率,因为IN子句将执行一个子查询内部的排序和合并。

9、避免在索引列上使用计算

在WHERE子句中,如果索引列是计算或者函数的一部分,DBMS的优化器将不会使用索引而使用全表扫描。

10、用UNION ALL替换UNION

当SQL语句需要UNION两个查询结果集合时,即使检索结果中不会有重复的纪录,使用UNION这两个结果集同样会尝试进行合并,然后在输出最终结果前进行排序。因此检索结果中不会有重复纪录的话,应该用UNION ALL,这样效率会得到提高。

11、避免使用隐式类型造成的全表扫描

比如A表的字符串类型字段level为人员的级别并且该字段建立了索引,如下SQL:SELECT id,level,name from A WHERE level=6;由于大部分数据库的隐式转换类型中数值类型的优先级高于字符串类型,因此DBMS将会对level字段进行隐式类型转换,相当于执行了SELECT id,level,name from A WHERE TO_INT(level)=6;由于该索引进行了计算,造成了索引失效而使用全表扫描,故应做如下修改:SELECT id,level,name from A WHERE level="6"。

12、防止检索范围过宽

如果DBMS优化器认为检索范围过宽,那么它将放弃索引查找而使用全表扫描。下面是可能造成检索范围过宽的情况:

  • 使用IS NOT NULL 或者不等于判断,可能造成优化器假设匹配的纪录数太多。

  • 使用LIKE的时候,“a%”将会使用索引,而“a%c”和“%c”则会使用全表扫描。

    如有不对之处欢迎指正,不胜感激。\

    最后祝大家新的一年事事顺心,万事如意!!!