SQL优化,主要是优化查询效率,查询有两种: 
1、全表扫描检索,不管查询什么数据,都是全表依次扫描去查询,数据量大的话,会大大降低性能。 
2、按照索引检索,根据索引去检索数据,速度会非常快。

 

SQL优化的手段

1、使用索引,在经常需要进行检索的字段上创建索引,可以大大的提供查询的效率,但是要注意合理的创建索引,因为索引虽然提高了查询效率,但是牺牲了其他方面的性能,比如:增加、删除、修改就会变慢,同时索引还会占据一定的存储空间,比如删除了记录,但索引是没被删除的,还会有一些索引碎片的问题,索引很好,但不要乱建。

# 在表中建立索引,优先考虑where、group by使用到的字段。内外连接 如:left join ...on ...   关联到的字段,也优先考虑索引

2、避免在索引列上计算,避免在索引列上使用函数,避免在索引列上使用not,避免在索引列使用<>不等于,避免在索引列上使用is null,is not null,避免改变索引列的数据类型(比如索引列是字符类型,如果你用数字类型去和他比较,Oracle会把索引列的字符类型隐示的转换成数字类型去比较),避免在索引列上使用模糊查询(会导致检索访问过广),
否则不避免,就会破坏索引,而使用全表扫描的方式,降低效率。

3、使用预编译查询,尽量使用参数化SQL,既可以防止SQL注入又可以利用预编译的SQL,预编译的好处是编译一次,以后就不需要编译了,直接使用预编译好的SQL,节省了DBMS(数据库管理系统)去编译的时间。

4、使用数据库内部函数和被数据库优化的语句,比如max()、between and等。

5、使用大写编写SQL语句(DBMS在解析SQL语句时,会检查SQL语句,若不是大写,会全部转换成大写)。

6、使用别名(DBMS解析SQL语句时会给列取别名),我们自己给表取别名,给字段列取别名,这样可以减少DBMS解析的时间并减少列名引起的歧义错误。

7、减少访问数据库的次数,减少查询的次数,尽量把多条SQL语句压缩成一条SQL语句,把频繁访问数据库的方式改成使用批处理。

8、避免使用”“,select 是一个非常低效的方法,DBMS在解析SQL语句的过程中会去数据字典表里查询该表对应的字段列,并依次按照顺序把 “* ” 转换成所有的列名,将消耗很多时间。

9、避免使用消耗资源的操作,带有distinct、union、minus、intersect、order by的SQL语句会启动SQL引擎,执行消耗资源的排序功能,distinct需要一次排序操作,其他的至少需要2次排序操作。

10、用where语句替换having语句,having语句只会在查询出所有记录后才对数据进行过滤,一般用于分组后,对分组的结果进行过滤,除此外,应该尽量在查询出记录之前通过where进行数据过滤。

11、用in、union来代替or。or的效率极低。

12、用union all来代替union,union会合并重复的数据,并排序,union all 不会合并重复的数据,不会排序。

13、exists来代替in,not exists 代替not in,in会对他里面的子查询进行排序及合并操作。

14、用关联查询(连表查询)来代替exists子查询,关联查询一般比子查询效率高。

15、用truncate来代替delete。delete是dml语句删除的内容,删除掉的数据可以通过rollback回滚回来,而truncate table 表名,是ddl语句删除的内容无法通过rollback回滚回来,truncate截断的意思。
delete语句DBMS会把刚刚操作的数据,保存到回滚段,并保存到commit后才能被清理掉。而truncate无需做这个工作,故效率要高很多。

16、exists来代替distinct、group by来代替distinct。

17、用>=代替>,<=代替<,比如deptno>3,应写成deptno>=4,前者DBMS要先定位到3的记录,并且向前扫描>3的记录,而后者直接定位到4,速度快很多。

18、用between and 代替<=,>=,因为between and是数据库优化的语句。

19、优化group by语句,把不需要分组的数据,提前通过where过滤掉。

20、优化where语句,把能过滤掉大量数据的条件放在where语句中靠前的位置,明确的过滤条件也应尽量放在靠前的位置,不明确的模糊查询的条件放在最后。

21、关联表查询时,把记录数较少的表,放在from子句中的右边,因为DBMS解析SQL时是从右到左的顺序,靠右边的表或结果集优先被处理。

22、在程序中尽量多的使用commit,这样程序的性能会得到提高,需求也会因为commit所释放的资源而减少,commit释放的资源:
1、回滚段上用于恢复的数据信息。
2、被程序语句获得的锁资源。
3、redo log buffer中的空间
4、Oracle为了管理上述3种资源的内部花费。
 ————————————————
 

------------------------------------------------------------------------------------------------------------------------------------------------------

### 例子 :

1、在表中建立索引,优先考虑where、group by使用到的字段。

2、尽量避免使用select *,返回无用的字段会降低查询效率。如下:

SELECT * FROM t 

优化方式:使用具体的字段代替*,只返回使用到的字段。

 

3、尽量避免使用in 和not in,会导致数据库引擎放弃索引进行全表扫描。如下:

SELECT * FROM t WHERE id IN (2,3)

SELECT * FROM t1 WHERE username IN (SELECT username FROM t2)

优化方式:如果是连续数值,可以用between代替。如下:

SELECT * FROM t WHERE id BETWEEN 2 AND 3

如果是子查询,可以用exists代替。如下:

SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.username = t2.username)

 

4、尽量避免使用or,会导致数据库引擎放弃索引进行全表扫描。如下:

SELECT * FROM t WHERE id = 1 OR id = 3

优化方式:可以用union代替or。如下:

SELECT * FROM t WHERE id = 1
UNION
SELECT * FROM t WHERE id = 3

(PS:如果or两边的字段是同一个,如例子中这样。貌似两种方式效率差不多,即使union扫描的是索引,or扫描的是全表)

 

5、尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描。如下:

SELECT * FROM t WHERE username LIKE '%li%'

优化方式:尽量在字段后面使用模糊查询。如下:

SELECT * FROM t WHERE username LIKE 'li%'

 

6、尽量避免进行null值的判断,会导致数据库引擎放弃索引进行全表扫描。如下:

SELECT * FROM t WHERE score IS NULL

优化方式:可以给字段添加默认值0,对0值进行判断。如下:

SELECT * FROM t WHERE score = 0

 

7、尽量避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描。如下:

SELECT * FROM t2 WHERE score/10 = 9

SELECT * FROM t2 WHERE SUBSTR(username,1,2) = 'li'

优化方式:可以将表达式、函数操作移动到等号右侧。如下:

SELECT * FROM t2 WHERE score = 10*9

SELECT * FROM t2 WHERE username LIKE 'li%'

 

8、当数据量大时,避免使用where 1=1的条件。通常为了方便拼装查询条件,我们会默认使用该条件,数据库引擎会放弃索引进行全表扫描。如下:

SELECT * FROM t WHERE 1=1

优化方式:用代码拼装sql时进行判断,没where加where,有where加and。

 

  其实,总结起来,大家应该也发现了,就是在查询的时候,要尽量让数据库引擎使用索引。而如何让数据库按我们的意思去使用索引就涉及到扫描参数(SARG)的概念。在数据库引擎在查询分析阶段,会使用查询优化器对查询的每个阶段(如一个带子查询的sql语句就存在不同的查询阶段)进行分析,来决定需要扫描的数据量。如果一个阶段可以被用作扫描参数,那么就可以限制搜索的数据量,从而一定程度上提高搜索效率。

SARG的定义:用于限制搜索的一个操作,因为它通常是指一个特定的匹配,一个值的范围内的匹配或者两个以上条件的AND连接。

 

  所以,我们要让我们写的查询条件尽量能够让引擎识别为扫描参数。具体做法,就如前面提到的这些方法。