我经常看到一些人在问,有没有优化的书啊?当然,如果你是开发人员或者是应用人员,你所说的优化,如果我没理解错的话,应该是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