我经常看到一些人在问,有没有优化的书啊?当然,如果你是开发人员或者是应用人员,你所说的优化,如果我没理解错的话,应该是SQL语句的优化。其实对于这个问题,我想简答的说几句,所谓优化,以我的理解,分道和术两个层面:


术:是实现方法


道:是理论思想




就好比武侠小说《笑傲江湖》中的华山派的剑宗、气宗之争。




先来说术


对于初学来说,可能对术更感兴趣,因为当你掌握了SQL语句的基本语法之后,如果你会一些优化的方法,马上就可以带来语句上的性能提升。比如改变语句的写法、在符合条件的列上添加索引、并行操作、使用提示、收集对象和系统的统计信息等。对于术来说,最大的问题在于,你需要记得方法很多,我刚才列出来的方法,也还只是其中的一部分,并且每一项都会有很多具体的变化要考虑。下面是一个关于索引的小例子,仅供参考。




$ sqlplus scott/tiger


SQL*Plus: Release 10.2.0.1.0 - Production on Tue Apr 3 00:12:54 2012、


Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:


Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production


With the Partitioning, OLAP and Data Mining options




首先建一个测试表,往表里添加30万的数据,模拟一个大表


scott@DB01> create table  s_test(id number,name varchar2(10),sal number);


Table created.




scott@DB01> begin


 2  for i in 1..100000 loop


 3  insert into s_test values(i,i+1,i);


 4  end loop;


 5  end;


 6  /


PL/SQL procedure successfully completed.




scott@DB01> /


PL/SQL procedure successfully completed.




scott@DB01> /


PL/SQL procedure successfully completed.




scott@DB01> commit;                  


Commit complete.




scott@DB01> select count(*) from s_test;


 COUNT(*)


----------


   300000




通过开启autotrace,我们来看SQL语句的执行计划,注意Cost的数值


scott@DB01> set autotrace trace exp




scott@DB01> select id,name,count(*) from s_test where id>=100 and id<=120 group by id,name;


Execution Plan


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


Plan hash value: 752916570


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


| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |


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


|   0 | SELECT STATEMENT   |        |    10 |   200 |   198   (3)| 00:00:03 |


|   1 |  HASH GROUP BY     |        |    10 |   200 |   198   (3)| 00:00:03 |


|*  2 |   TABLE ACCESS FULL| S_TEST |    10 |   200 |   197   (3)| 00:00:03 |


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


Predicate Information (identified by operation id):


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


  2 - filter("ID">=100 AND "ID"<=120)


Note


-----


  - dynamic sampling used for this statement


scott@DB01>


我们注意到在没有索引的一个大表上,当我们使用上边的语句做查询的时候,成本(Cost)是198




通过对表里数据和语句的简单分析(其实这里就是道),我们在id和name列上建一个组合索引


scott@DB01> create index s_test_id_n_idx on s_test(id,name);


Index created.




scott@DB01> select id,name,count(*) from s_test where id>=100 and id<=120 group by id,name;


Execution Plan


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


Plan hash value: 4197561916


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


| Id  | Operation            | Name            | Rows  | Bytes | Cost (%CPU)| Time     |


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


|   0 | SELECT STATEMENT     |                 |    63 |  1260 |     3   (0)| 00:00:01 |


|   1 |  SORT GROUP BY NOSORT|                 |    63 |  1260 |     3   (0)| 00:00:01 |


|*  2 |   INDEX RANGE SCAN   | S_TEST_ID_N_IDX |    63 |  1260 |     3   (0)| 00:00:01 |


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


Predicate Information (identified by operation id):


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


  2 - access("ID">=100 AND "ID"<=120)


      filter("ID">=100 AND "ID"<=120)


Note


-----


  - dynamic sampling used for this statement


我们注意到,语句的成本(Cost)是3,大幅度下降,如果反映到语句的执行速度上,你会发现语句执行的速度明显变快。






对于术来说,最大的问题是只是知道该怎么做,而不知道为什么要这么做,更不知道,是不是每个数据库版本都要这么做呢?术是从局部,比如某一个SQL入手的,而道是整体,从应用层面,从整个数据库角度来思考的。所以,如果你想达到SQL优化的更高境界,一定要会道的东西。道在术先,就好比应用和开发的设计要先于代码的设计。所谓道,就是从根本上知道调优SQL语句的目的?你所做的操作,到底对Oracle数据库有什么影响?从这个角度来讲,你需要知道你的应用是什么类型(OLAP、OLTP、混合)的、你所操作的数据库是什么样子的(架构)、数据库是如何工作的、SQL语句在数据库内部是如何执行的、数据库的设计基本原则、存储对象(heap、partition、IOT、cluster)的选择等。道,其实最终的目的是让你使用最少的资源(CPU、IO、NETWORK、MEMORY等),却能得到最快的相应时间。当你了解了这些之后,你才会有一个全面系统地把握,知道如何去调整语句,至于具体的实现,就是术的问题了。




比如SQL语句共享,可以节省CPU和内存,在OLTP系统中,建议使用绑定变量或修改参数来达到共享语句的目的。




对于SQL优化的书,我没有什么好的建议,我只能说SQL、PLSQL、ORACLE体系架构、SQL Tuning 这些教材就是很不错的。如果你具有一定的基础,看看TOM的《Oracle9i&10g编程艺术》,相信这本书一定会让你受益匪浅的。


oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html