ORACLE SQL性能优化系列 (一)

** 1. ** ** 选用适合的 ORACLE ** ** 优化器 **

ORACLE 的优化器共有 3 种 :

a. RULE ( 基于规则 ) b. COST ( 基于成本 ) c. CHOOSE ( 选择性 )

设置缺省的优化器 , 可以通过对 init.ora 文件中 OPTIMIZER_MODE 参数的各种声明 , 如 RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你当然也在 SQL 句级或是会话 (session) 级对其进行覆盖 .

为了使用基于成本的优化器 (CBO, Cost-Based Optimizer) , 你必须经常运行 analyze 命令 , 以增加数据库中的对象统计信息 (object statistics) 的准确性 .

如果数据库的优化器模式设置为选择性 (CHOOSE), 那么实际的优化器模式将和是否运行过 analyze 命令有关 . 如果 table 已经被 analyze 过 , 优化器模式将自动成为 CBO , 反之 , 数据库将采用 RULE 形式的优化器 .

在缺省情况下 ,ORACLE 采用 CHOOSE 优化器 , 为了避免那些不必要的全表扫描 (full table scan) , 你必须尽量避免使用 CHOOSE 优化器 , 而直接采用基于规则或者基于成本的优化器 .

** 2. ** ** 访问 Table ** ** 的方式 **

ORACLE 采用两种访问表中记录的方式 :

a. 全表扫描

全表扫描就是顺序地访问表中每条记录 . ORACLE 采用一次读入多个数据块 (database block) 的方式优化全表扫描 .

b. 通过 ROWID 访问表

你可以采用基于 ROWID 的访问方式情况 , 提高访问表的效率 , , ROWID 包含了表中记录的物理位置信息 ..ORACLE 采用索引 (INDEX) 实现了数据和存放数据的物理位置 (ROWID) 之间的联系 . 通常索引提供了快速访问 ROWID 的方法 , 因此那些基于索引列的查询就可以得到性能上的提高 .

** 3. ** ** 共享 SQL ** ** 语句 **

为了不重复解析相同的 SQL 语句 , 在第一次解析之后 , ORACLE 将 SQL 语句存放在内存中 . 这块位于系统全局区域 SGA(system global area) 的共享池 (shared buffer pool) 中的内存可以被所有的数据库用户共享 . 因此 , 当你执行一个 SQL 语句 ( 有时被称为一个游标 ) 时 , 如果它

和之前的执行过的语句完全相同 , ORACLE 就能很快获得已经被解析的语句以及最好的

执行路径 . ORACLE 的这个功能大大地提高了 SQL 的执行性能并节省了内存的使用 .

可惜的是 ORACLE 只对简单的表提供高速缓冲 (cache buffering) , 这个功能并不适用于多表连接查询 .

数据库管理员必须在 init.ora 中为这个区域设置合适的参数 , 当这个内存区域越大 , 就可以保留更多的语句 , 当然被共享的可能性也就越大了 .

当你向 ORACLE 提交一个 SQL 语句 ,ORACLE 会首先在这块内存中查找相同的语句 .

这里需要注明的是 ,ORACLE 对两者采取的是一种严格匹配 , 要达成共享 ,SQL 语句必须

完全相同 ( 包括空格 , 换行等 ).

共享的语句必须满足三个条件 :

A. 字符级的比较 :

当前被执行的语句和共享池中的语句必须完全相同 .

例如 :

SELECT * FROM EMP;

和下列每一个都不同

SELECT * from EMP;

Select * From Emp;

SELECT * FROM EMP;

B. 两个语句所指的对象必须完全相同 :

例如 :

用户 对象名 如何访问

Jack sal_limit private synonym

Work_city public synonym

Plant_detail public synonym

Jill sal_limit private synonym

Work_city public synonym

Plant_detail table owner

考虑一下下列 SQL 语句能否在这两个用户之间共享 .

** SQL **

|

** 能否共享 **

|

** 原因 **

---|---|---

select max(sal_cap) from sal_limit;

|

不能

|

每个用户都有一个 private synonym - sal_limit , 它们是不同的对象

select count(*0 from work_city where sdesc like 'NEW%';

|

|

两个用户访问相同的对象 public synonym - work_city

select a.sdesc,b.location from work_city a , plant_detail b where a.city_id = b.city_id

|

不能

|

用户 jack 通过private synonym访问plant_detail 而jill 是表的所有者,对象不同.

C. 两个 SQL 语句中必须使用相同的名字的绑定变量 (bind variables)

例如:

第一组的两个 SQL 语句是相同的 ( 可以共享 ), 而第二组中的两个语句是不同的 ( 即使在运行时 , 赋于不同的绑定变量相同的值 )

a.

select pin , name from people where pin = :blk1.pin;

select pin , name from people where pin = :blk1.pin;

b.

select pin , name from people where pin = :blk1.ot_ind ;

select pin , name from people where pin = :blk1.ov_ind ;

(待续)

Published At
Categories with 数据库类
comments powered by Disqus