没有合适的资源?快使用搜索试试~ 我知道了~
ORACLE的执行计划,ORACLE的执行计划
资源详情
资源评论
资源推荐
【内容导航】
第 1 页:背景知识
第 2 页:Rowid 的概念
第 3 页:可选择性
第 4 页:执行计划的步骤
第 5 页:访问路径(方法) -- access path
第 6 页:4 种类型的索引扫描
第 7 页:表之间的连接
第 8 页:嵌套循环(Nested Loops, NL)
第 9 页:如何产生执行计划
第 10 页:如何分析执行计划
第 11 页:对于 RBO 优化器
第 12 页:对于 CBO 优化器
第 13 页:如何干预执行计划 - - 使用 hints 提示
第 14 页:使用全套的 hints
第 15 页:具体案例分析
文本 Tag: Oracle 数据库 Oracle 数据库开发
背景知识:
为了更好的进行下面的内容我们必须了解一些概念性的术语:
共享 sql 语句
为了不重复解析相同的 SQL 语句(因为解析操作比较费资源,会导致性能下降),在第一
次解析之后,ORACLE 将 SQL 语句及解析后得到的执行计划存放在内存中。这块位于系统全
局区域 SGA(system global area)的共享池(shared buffer pool)中的内存可以被所有的数
据库用户共享。因此,当你执行一个 SQL 语句(有时被称为一个游标)时,如果该语句和之前
的执行过的某一语句完全相同,并且之前执行的该语句与其执行计划仍然在内存中存在,则
ORACLE 就不需要再进行分析,直接得到该语句的执行路径。ORACLE 的这个功能大大地提高
了 SQL 的执行性能并大大节省了内存的使用。使用这个功能的关键是将执行过的语句尽可能
放到内存中,所以这要求有大的共享池(通过设置 shared buffer pool 参数值)和尽可能的
使用绑定变量的方法执行 SQL 语句。
当你向 ORACLE 提交一个 SQL 语句,ORACLE 会首先在共享内存中查找是否有相同的语句。
这里需要注明的是,ORACLE 对两者采取的是一种严格匹配,要达成共享,SQL 语句必须完全
相同(包括空格,换行等)。
下面是判断 SQL 语句是否与共享内存中某一 SQL 相同的步骤:
1). 对所发出语句的文本串进行 hashed。如果 hash 值与已在共享池中 SQL 语句的 hash
值相同,则进行第 2 步:
2) 将所发出语句的文本串(包括大小写、空白和注释)与在第 1 步中识别的所有
已存在的 SQL 语句相比较。
例如:
SELECT * FROM emp WHERE empno = 1000;
和下列每一个都不同
SELECT * from emp WHERE empno = 1000;
SELECT * FROM EMP WHERE empno = 1000;
SELECT * FROM emp WHERE empno = 2000;
在上面的语句中列值都是直接 SQL 语句中的,今后我们将这类 sql 成为硬编码 SQL
或字面值 SQL
使用绑定变量的 SQL 语句中必须使用相同的名字的绑定变量(bind variables) ,
例如:
a. 该 2 个 sql 语句被认为相同
select pin , name from people where pin = :blk1.pin;
select pin , name from people where pin = :blk1.pin;
b. 该 2 个 sql 语句被认为不相同
select pin , name from people where pin = :blk1.ot_ind;
select pin , name from people where pin = :blk1.ov_ind;
今后我们将上面的这类语句称为绑定变量 SQL。
3). 将所发出语句中涉及的对象与第 2 步中识别的已存在语句所涉及对象相比较。
例如:
如用户 user1 与用户 user2 下都有 EMP 表,则
用户 user1 发出的语句:SELECT * FROM EMP; 与
用户 user2 发出的语句:SELECT * FROM EMP; 被认为是不相同的语句,
因为两个语句中引用的 EMP 不是指同一个表。
4). 在 SQL 语句中使用的捆绑变量的捆绑类型必须一致。
如果语句与当前在共享池中的另一个语句是等同的话,Oracle 并不对它进行语法分析。
而直接执行该语句,提高了执行效率,因为语法分析比较耗费资源。
注意的是,从 oracle 8i 开始,新引入了一个 CURSOR_SHARING 参数,该参数的主要目
的就是为了解决在编程过程中已大量使用的硬编码 SQL 问题。因为在实际开发中,很多程序
人员为了提高开发速度,而采用类似下面的开发方法:
str_sql string;
int_empno int;
int_empno = 2000;
str_sql = ‘SELECT * FROM emp WHERE empno = ‘ + int_empno;
„„„„
int_empno = 1000;
str_sql = ‘SELECT * FROM emp WHERE empno = ‘ + int_empno;
上面的代码实际上使用了硬编码 SQL,使我们不能使用共享 SQL 的功能,结果是数据库
效率不高。但是从上面的 2 个语句来看,产生的硬编码 SQL 只是列值不同,其它部分都是相
同的,如果仅仅因为列值不同而导致这 2 个语句不能共享是很可惜的,为了解决这个问题,
引入了 CURSOR_SHARING 参数,使这类问题也可以使用共享 SQL,从而使这样的开发也可以
利用共享 SQL 功能。听起来不错,ORACLE 真为用户着想,使用户在不改变代码的情况下还
可以利用共享 SQL 的功能。真的如此吗?天上不会无缘无故的掉一个馅饼的,ORACLE 对该参
数的使用做了说明,建议在经过实际测试后再改该参数的值(缺省情况下,该参数的值为
EXACT,语句完全一致才使用共享 SQL)。因为有可能该变该值后,你的硬编码 SQL 是可以使
用共享 SQL 了,但数据库的性能反而会下降。 我在实际应用中已经遇到这种情况。所以建
议编写需要稳定运行程序的开发人员最好还是一开始就使用绑定变量的 SQL。
点此发表你的看法>>【已有位网友发表了看法】
Rowid 的概念:
rowid 是一个伪列,既然是伪列,那么这个列就不是用户定义,而是系统自己给加上的。对每个表都
有一个 rowid 的伪列,但是表中并不物理存储 ROWID 列的值。不过你可以像使用其它列那样使用它,但是
不能删除改列,也不能对该列的值进行修改、插入。一旦一行数据插入数据库,则 rowid 在该行的生命周
期内是唯一的,即即使该行产生行迁移,行的 rowid 也不会改变。
为什么使用 ROWID
rowid 对访问一个表中的给定的行提供了最快的访问方法,通过 ROWID 可以直接定位
到相应的数据块上,然后将其读到内存。我们创建一个索引时,该索引不但存储索引列的值,而且也
存储索引值所对应的行的 ROWID,这样我们通过索引快速找到相应行的 ROWID 后,通过该 ROWID,就可以迅
速将数据查询出来。这也就是我们使用索引查询时,速度比较快的原因。
在 ORACLE8 以前的版本中,ROWID 由 FILE 、BLOCK、ROW NUMBER 构成。随着 oracle8 中对象概念的扩
展,ROWID 发生了变化,ROWID 由 OBJECT、FILE、BLOCK、ROW NUMBER 构成。利用 DBMS_ROWID 可以将 rowid
分解成上述的各部分,也可以将上述的各部分组成一个有效的 rowid。
Recursive SQL 概念
有时为了执行用户发出的一个 sql 语句,Oracle 必须执行一些额外的语句,我们将这些额外的语句称
之为'recursive calls'或'recursive SQL statements'。如当一个 DDL 语句发出后,ORACLE 总是隐含的
发出一些 recursive SQL 语句,来修改数据字典信息,以便用户可以成功的执行该 DDL 语句。当需要的数
据字典信息没有在共享内存中时,经常会发生 Recursive calls,这些 Recursive calls 会将数据字典信
息从硬盘读入内存中。用户不比关心这些 recursive SQL 语句的执行情况,在需要的时候,ORACLE 会自动
的在内部执行这些语句。当然 DML 语句与 SELECT 都可能引起 recursive SQL。简单的说,我们可以将触发
器视为 recursive SQL。
Row Source(行源)
用在查询中,由上一操作返回的符合条件的行的集合,即可以是表的全部行数据的集合;也可以是表的
部分行数据的集合;也可以为对上 2 个 row source 进行连接操作(如 join 连接)后得到的行数据集合。
Predicate(谓词)
一个查询中的 WHERE 限制条件
Driving Table(驱动表)
该表又称为外层表(OUTER TABLE)。这个概念用于嵌套与 HASH 连接中。如果该 row source 返回较多的
行数据,则对所有的后续操作有负面影响。注意此处虽然翻译为驱动表,但实际上翻译为驱动行源(driving
row source)更为确切。一般说来,是应用查询的限制条件后,返回较少行源的表作为驱动表,所以如果一
个大表在 WHERE 条件有有限制条件(如等值限制),则该大表作为驱动表也是合适的,所以并不是只有较小
的表可以作为驱动表,正确说法应该为应用查询的限制条件后,返回较少行源的表作为驱动表。在执行计
划中,应该为靠上的那个 row source,后面会给出具体说明。在我们后面的描述中,一般将该表称为连接
操作的 row source 1。
Probed Table(被探查表)
该表又称为内层表(INNER TABLE)。在我们从驱动表中得到具体一行的数据后,在该表中寻找符合连接
条件的行。所以该表应当为大表(实际上应该为返回较大 row source 的表)且相应的列上应该有索引。在我
们后面的描述中,一般将该表称为连接操作的 row source 2。
组合索引(concatenated index)
由多个列构成的索引,如 create index idx_emp on emp(col1, col2, col3, „„),则我们称 idx_emp
索引为组合索引。在组合索引中有一个重要的概念:引导列(leading column),在上面的例子中,col1 列
为引导列。当我们进行查询时可以使用”where col1 = ? ”,也可以使用”where col1 = ? and col2 = ?”,
这样的限制条件都会使用索引,但是”where col2 = ? ”查询就不会使用该索引。所以限制条件中包含先
导列时,该限制条件才会使用该组合索引。
点此发表你的看法>>【已有位网友发表了看法】
可选择性(selectivity):
比较一下列中唯一键的数量和表中的行数,就可以判断该列的可选择性。如果该列的”唯一键的数量/
表中的行数”的比值越接近 1,则该列的可选择性越高,该列就越适合创建索引,同样索引的可选择性也
越高。在可选择性高的列上进行查询时,返回的数据就较少,比较适合使用索引查询。
剩余38页未读,继续阅读
lzq198491
- 粉丝: 1
- 资源: 37
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0