INDEX_JOIN
这里就以INDEX_JOIN为例,简单描述一下如何影响Oracle的执行计划的产生。
控制执行计划最简单的方法莫过于使用HINT,这篇文章要介绍的是,在不使用HINT的情况下,让Oracle产生INDEX_JOIN执行计划。
下面先构造查询所用的表,问题中使用的表是HR用户下的EMPLOYEES。如果hr用户不存在,Oracle9i可以通过$ORACLE_HOME/demo/schema/human_resources/hr_main.sql来创建用户。
SQL> CREATE TABLE EMPLOYEES AS SELECT * FROM HR.EMPLOYEES;
表已创建。
SQL> SELECT COUNT(*) FROM EMPLOYEES;
COUNT(*)
----------
107
已选择 1 行。
查询语句为:
SQL> SET AUTOT TRACE
SQL> SELECT EMPLOYEE_ID, SALARY
2 FROM EMPLOYEES
3 WHERE SALARY > 2000;
已选择107行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'EMPLOYEES'
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
12 consistent gets
0 physical reads
0 redo size
2273 bytes sent via SQL*Net to client
580 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
107 rows processed
需要采用索引连接,首先将两个索引建立起来。而且索引连接是CBO才能采用的执行计划,因此对表和索引进行分析。
SQL> ALTER TABLE EMPLOYEES ADD CONSTRAINT PK_EMPLOYEES PRIMARY KEY (EMPLOYEE_ID);
表已更改。
SQL> CREATE INDEX IND_EMP_SALARY ON EMPLOYEES (SALARY);
索引已创建。
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'EMPLOYEES', CASCADE => TRUE)
PL/SQL 过程已成功完成。
再次执行上面的SQL:
SQL> SELECT EMPLOYEE_ID, SALARY
2 FROM EMPLOYEES
3 WHERE SALARY > 2000;
已选择107行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=107 Bytes=856)
1 0 TABLE ACCESS (FULL) OF 'EMPLOYEES' (Cost=2 Card=107 Bytes=856)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
12 consistent gets
0 physical reads
0 redo size
2273 bytes sent via SQL*Net to client
580 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
107 rows processed
Oracle执行的仍然是全表扫描,但是优化器以及是CBO了。先通过HINT,看看现在是否已经满足了INDEX_JOIN执行计划的执行条件:
SQL> SELECT /*+ INDEX_JOIN(EMPLOYEES PK_EMPLOYEES IND_EMP_SALARY) */
2 EMPLOYEE_ID, SALARY
3 FROM EMPLOYEES
4 WHERE SALARY > 2000;
已选择107行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=107 Bytes=856)
1 0 VIEW OF 'index$_join$_001' (Cost=4 Card=107 Bytes=856)
2 1 HASH JOIN
3 2 INDEX (RANGE SCAN) OF 'IND_EMP_SALARY' (NON-UNIQUE) (Cost=3 Card=107 Bytes=856)
4 2 INDEX (FAST FULL SCAN) OF 'PK_EMPLOYEES' (UNIQUE) (Cost=3 Card=107 Bytes=856)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
12 consistent gets
0 physical reads
0 redo size
2273 bytes sent via SQL*Net to client
580 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
107 rows processed
现在Oracle执行INDEX_JOIN的条件已经满足,Oracle之所以没有选择INDEX_JOIN而选择全表扫描,是因为Oracle认为全表扫描的代价比INDEX_JOIN要低。
不使用HINT,而让Oracle选择INDEX_JOIN,就必须让Oracle认为全表扫描的代价比INDEX_JOIN要高。
最直接的办法是修改Oracle收集的统计信息,通过这种方法来使Oracle认为表扫描的搭建远远大于通过索引连接的代价。
SQL> SELECT NUM_ROWS, BLOCKS FROM USER_TABLES WHERE TABLE_NAME = 'EMPLOYEES';
NUM_ROWS BLOCKS
---------- ----------
107 2
现在的统计信息显示,全部数据存储在两个BLOCK中,Oracle当然认为全部扫描的代价低,如果设置表统计信息中BLOCK的数量很大,Oracle就会认识到全表扫描的代价比较大。
SQL> EXEC DBMS_STATS.SET_TABLE_STATS(USER, 'EMPLOYEES', NUMROWS => 100, NUMBLKS => 100)
PL/SQL 过程已成功完成。
SQL> SELECT EMPLOYEE_ID, SALARY
2 FROM EMPLOYEES
3 WHERE SALARY > 2000;
已选择107行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=100 Bytes=800)
1 0 VIEW OF 'index$_join$_001' (Cost=4 Card=100 Bytes=800)
2 1 HASH JOIN
3 2 INDEX (RANGE SCAN) OF 'IND_EMP_SALARY' (NON-UNIQUE) (Cost=3 Card=100 Bytes=800)
4 2 INDEX (FAST FULL SCAN) OF 'PK_EMPLOYEES' (UNIQUE) (Cost=3 Card=100 Bytes=800)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
12 consistent gets
0 physical reads
0 redo size
2273 bytes sent via SQL*Net to client
580 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
107 rows processed
通过设置Oracle的统计信息的方法,让目标执行计划的代价最小,从而使得Oracle选择了预期的执行计划。
转载 http://yangtingkun.itpub.net/post/468/357542
INDEX_JOIN的更多相关文章
- Oracle的优化器介绍
Oracle优化器介绍 本文讲述了Oracle优化器的概念.工作原理和使用方法,兼顾了Oracle8i.9i以及最新的10g三个版本.理解本文将有助于您更好的更有效的进行SQL优化工作. RBO优化器 ...
- oracle 关键字
Oracle 关键字(保留字) DBA账户下执行SQL语句:select * from v$reserved_words ; 可得到所有的关键字: 1 ! 1 2 & 1 3 ( 1 4 ...
- 如何查看oracle数据库的所有的关键字
管理员账户登录后,执行以下命令: select * from v$reserved_words 附上参考: NOMONITORINGRECORDS_PER_BLOCKCASCADEDYNAMIC_S ...
- Oracle提示大全
Hint概述 基于代价的优化器是很聪明的,在绝大多数情况下它会选择正确的优化器,减轻了DBA的负担.但有时它也聪明反被聪明误,选择了很差的执行计划,使某个语句的执行变得奇慢无比. 此时就需要DBA进行 ...
- ORACLE常用SQL优化hint语句
在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法: 1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量, ...
- Oracle Hints详解
在向大家详细介绍Oracle Hints之前,首先让大家了解下Oracle Hints是什么,然后全面介绍Oracle Hints,希望对大家有用.基于代价的优化器是很聪明的,在绝大多数情况下它会选择 ...
- 基于Oracle的SQL优化(社区万众期待 数据库优化扛鼎巨著)
基于Oracle的SQL优化(社区万众期待数据库优化扛鼎巨著) 崔华 编 ISBN 978-7-121-21758-6 2014年1月出版 定价:128.00元 856页 16开 编辑推荐 本土O ...
- Oracle性能优化之SQL语句
1.SQL语句执行过程 1.1 SQL语句的执行步骤 1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义. 2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限. ...
- 常见Oracle HINT的用法
1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化. 例如: SELECT /*+ALL+_ROWS*/ EMP_NO,EMP_NAM,DAT_I ...
随机推荐
- 【查找结构4】红黑树 [RBT]
红黑树的性质与定义 红黑树(red-black tree) 是一棵满足下述性质的二叉查找树: 1. 每一个结点要么是红色,要么是黑色. 2. 根结点是黑色的. 3. 所有叶子结点都是黑色的(实际上都是 ...
- 【总结】杂谈Java异常处理
软件开发中一个古老的说法是:80%的工作使用20%的时间.80%是指检查和处理错误所付出的努力.在许多语言中,编写检查和处理错误的程序代码很乏味,并使应用程序代码变得冗长.原因之一就是它们的错误处理方 ...
- Java:Object类
objcet类中涉及的多态的扩展性,由于Object是所有类的根类,所以它可以接收任意类型的数据,包括基本数据类型.因为这一特点,它可以对多态性进行扩展. 1.创建一个Demo类来判断类类型 clas ...
- C# 窗体间传值方法大汇总
第一种方法:创建一个类,里面声明用于存储接收的字段.传的时候存储于字段中,要用的时候,直接类名.字段名 进行调用.(这种方法传递是双向的) 第二种方法:1.在Form1里定义 public strin ...
- 卷积神经网络CNN全面解析
卷积神经网络(CNN)概述 从多层感知器(MLP)说起 感知器 多层感知器 输入层-隐层 隐层-输出层 Back Propagation 存在的问题 从MLP到CNN CNN的前世今生 CNN的预测过 ...
- Zn离子参数
Generating Topology and Coordinates Files Using xLeap (AmberTools V1.5) Parameter and example files: ...
- LA 4255 Guess
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- oracle数据库sql的基本使用
整理了下关于oracle数据库中SQL的基本使用语句,整理如下,方便记忆. oracle的基本术语 数据字典,数据库元数据信息的数据字典表和用户可以读取的数据字典视图组成.存放oracle数据库所用的 ...
- 【CCS仿真】如何将CCS仿真时memory中的数据以Hex、Integer、 Long 、Float、 Addressable Unit类型保存到PC
2013-12-04 19:07:05 将在CCS中仿真的数据导入电脑上时,可以选择不同的数据类型,以便分析,具体方法如下: 在CCS菜单中,选择File—>Data—>Save,弹出以下 ...
- java 文件text的写入
日志文件 OutputStream out = new FileOutputStream(f, true); if (list1.size() > 0) { int h1 = 0; for (i ...