得到一条sql语句执行计划的常用方法:
1、explain plan 命令
2、DBMS_XPLAN包
3、sqlplus中的AUTOTRACE开关
4、10046事件
5、10053事件
6、AWR报告或者statspack报告
对于常用方法F5,其实是explain plan的封装
explain plan for +目标sql
select * from table(dbms_xplan.displan)
这里说一下两个关键字的作用: cardinality 实际上表示对目标sql的某个具体执行步骤的执行结果所包含的记录数的估算。cardinality的值越大,他所对应的成本往往也就越高,那么这个执行步骤对应的
执行路径的总成本也就越大。
2、使用DBMS_XPLAN包
针对不同的应用场景,可以选择以下四种方法
1、select * from table(dbms_xplan.displan)
2、select * from table(dbms_xplan.displan_cuecsor(null,null,'advanced'));
3、select * from table (dbms_xplan.displan_cursor('sql_id/hash_value',child_cursor_number),'advanced')
4、select * from table (dbms_xplan.displan_awr('sql_id'))
方法2 是用来查看刚刚执行过的sql 的执行过程
方法3是用来查看指定sql 的执行计划
方法4是用来查看指定sql 的历史所有执行计划
3、AUTOTRACE开关
在sqlplus中将AUTOTRACE开关打开也能得到目标sql的执行计划,而且初次之外,还能得到目标sql在执行时的资源消耗量,即通过设置AUTOTRACE开关我们可以额外观察到目标sql执行时所耗费的物理读、逻辑读、产生的redo数量以及排序数量等。
具体使用方法:
set AUTOTRACE ON
select * from .......
对于oracle中hint的知识点:
1、hint实际上一种特殊的注释,它以一种固定的格式和位置出现在sql语句的sql文本之中,它可以影响优化器对于执行计划的选择,但这种影响不是强制性的,优化器在某些情况下可能会忽略掉sql中的hint,及时这个hint在语法和语义上是有效的。
2、hint的使用格式
/*+<具体的hint内容>*/
1) /*+full(tablename)*/ --全表扫描 在hint中指定具体的表名的时候,如果该表在对应sql文本中有别名(alias),则应该使用该表的别名
2)/*+ALL_ROWS*/ --针对整个目标sql的hint,它的含义是让优化器启用CBO,会选择吞吐量最佳的执行路径
3)/*+FIRST_ROWS(n)*/ --在得到目标sql的执行计划时,会选择那些能以最快的响应时间返回头n条记录的执行计划
4)/*+rule*/ --表示对目标sql启用RBO
有一下情形,rule hint会被oracel忽略
a) 目标sql除rule之外还使用了其他的hint
b) 目标sql使用了并行
c) 目标sql所涉及的对象有IOT
d)目标对象所涉及的sql有分区
5) /*+rowid(目标表)*/ --rowid是针对单个目标表的hint,它的含义是让目标表执行rowid扫描,只要目标表中使用了含rowid的where条件时rowid hint 才有意义
6)/*+ index (目标表 目标表索引)*/
格式二 /*+index (目标表 目标索引1 目标索引2 目标索引3 。。。。)*/
格式三 /*+ index (目标表 (目标索引1的索引列名)(目标索引2的索引列名)....(目标索引n的索引列名))*/
7) /*+NO_INDEX*/ --让目标表不走某个索引
8)/*+INDEX_DESC*/ --让目标索引执行索引降序索引扫描操作
9)/*+INDEX_COMBINE* / --针对单个表的目标索引,它的含义是让优化器对目标表上的多个目标索引执行位图布尔运算
10) /*+INDEX_FFS*/ 是执行单个目标表的hint,它的含义是让优化器目标表上的目标索引执行索引快速全表扫描操作
注: 索引快速全表扫描操作成立的前提条件是select语句中的所有查询列都位于目标索引之中,即通过扫描目标索引就可以得到所有的查询列而不用回表
11) /*+index_join*/ --它的含义是让优化器对目标表上的多个目标索引执行index join操作
注: index_join能成立的前提条件是select语句中的所有查询列都位于目标索引之中,即通过扫描目标索引就可以得到所有的查询列而不用回表
12) /*+AND_EQUAL*/ --让目标表上的多个目标索引执行index merge 操作
注:index merge 能成立的前提条件是目标sql的where条件里出现了多个针对不同单列的等值条件,并且这些列上都有单键值的索引,在oracle数据库中能做index merge的索引数量的最大值是5
------*与表连接顺序相关的索引*--------
/*+ordered*/ --ordered是针对多个目标表的hint,它的含义就是让优化器对目标表执行表连接操作时,按照他们在目标sql的from字句中出现的顺序从左到右依次进行连接
/*+leading*/ --是针对多个目标表的hint,它的含义是让优化器将我们指定的多个表的连接结果作为目标sql表连接过程中的驱动结果集,并且将leading hint中 从左至右出现的第一个目标表作为整个表连接过程中的首个驱动表
-------*与表连接方法相关的hint*--------
/*+use_merge*/ --让优化器将我们指定的多个表作为被驱动表与其他的表或结果集做排序合并连接
/*+use_NL*/ --让优化器将我们指定的多个表作为被驱动表与其他表或者结果集进行嵌套循环连接
/*+use_hash*/ --让优化器将我们指定的多个表作为被驱动表与其他表或结果集做哈希连接
注:use_hash 中指定的目标表应该是哈希连接中的被驱动表
/*+merge_aj*/ -- 针对子查询的hint,让优化器对相关目标表执行排序合并反连接
/*+NL_AJ*/ --针对子查询的hint,让优化器对相关目标表执行嵌套循环反连接
/*+hash_aj*/ 针对子查询的hint,让优化器对相关目标表执行哈希反连接
/*+merge_sj*/ 针对子查询的hint,让优化器对目标表执行排序合并半连接
/*+NL_SJ*/ 针对子查询的hint,让优化器对相关目标表执行嵌套循环半连接
/*+hash_sj*/ 针对子查询的hint,让优化器对相关目标表执行哈希半连接
/*+use_concat*/ 针对整个目标sql的hint ,它的含义是让优化器对目标sql使用IN_list扩展或or扩展
/*+NO_expand*/ 不让目标执行IN—LIST或者or扩展
/*+merge*/ --对目标试图执行视图合并,
/*+unnest*/ --针对子查询的hint,让优化器对目标sql中的zi查询执行查询展开
/*+parallel*/ --sql总是以并行的方式执行,oracle此时会计算出一个并行度,这个计算出来的并行度总是大于或等于2
/*+parallel(auto)*/ --oracle同样会计算出一个并行度,但是这个计算出来的并行度可能是1,所以该格式的目标sql不一定总是会以并行的方式执行,当计算出的并行度为1的时候,该sql以串行的方式执行
/driving_site/ --针对单个目标表的hint,其含义是让优化器在我们指定的目标表所在的节点上执行目标sql ,适用于带dblink的分布式查询语句
/*+APPEND*/ --针对整个目标sql 的hint,其含义是让优化器在执行带子查询的insert 语句 时绕开buffer cache,使用直接路径插入。默认情况下,oracle在执行插入语句时使用的常规插入方式,这时相关的数据块会缓存在buffer cache 中,对于直接路径插入,oracle 在插入数据的时候,会直接在高水位线以上插入数据(然后在抬高高水位线),而不是像常规插入那样先去目标表的高水位线一下寻找是否存在插入数据的数据块,这样就省去了寻找合适数据块的开销。在非归档模式,或者在规定模式但表是NOLOGGING时,使用 append hint插入数据时不会产生redo,这样就省去了产生redo这部分工作的开销
注:当我们使用了有效的append hint 以直接路径插入对目标表insert数据时,oracle会在目标表加上LMODE=6的排它锁(TM ENQUEUE),这就意味着在插入数据时,其他人无法对目标表做任何DML操作,容易引起并发问题 。
/*+push_subq*/ --通常情况下,目标sql中不能做子查询展开的子查询总是在其执行计划的最后一步才被执行,但如果执行这个子查询后能显著减少返回结果集的数量,则先执行这个子查询就有可能提高该sql的执行效率
执行计划中的关键字cardinalty:某个执行步骤所对应的cardinality的值越大,那么他所对应的成本值往往就越高,这个执行步骤所在的执行路径的总成本也就越大。
可选择率selectivity和成本值得估算是息息相关的,可选择率的值越大,就意味着返回结果集的cardinality的值就越大,所以估算出来的成本值也就越大。
selectivity = 1/num_distnct num_distinct --指目标列distinct的值得数量