您的位置:首页 > 数据库 > Oracle

8 访问路径介绍--优化主题系列

2017-09-29 10:15 190 查看
8.1 tableaccess full

TABLE ACCESS FULL 全表扫描,多块读,等待事件:db file scattered read

如果是并行全表扫描,等待事件:direct path read

11g 有个新特征,在进行全表扫描的时候也会产生direct path read

在OLTP环境中要通过 10949event禁止该新特征

在OLAP环境中可以不用禁止

如果表上面有大量的行迁链接,会是单块读等待事件表现为db filesequential read

如果表上面发生了一个大事物,全表扫描会从UNDO读取前镜像,也会是单块读

HINT: FULL(表名/别名)

 

提问:假设test表有10GB的数据如果没有索引是不是走全表扫描??

select id from test where owner='SYS';

全表扫描是只扫描id和 owner列还是全扫??是不是
10GB的数据全部扫一遍??

高水位下的都扫对吧??这个时候可以看是不是碎片太多了??是不是经常DML碎片就多??

如果是并行全表扫描,等待事件:direct path read

8.2 rowidscan

ROWID SCAN   根据ROWID取得数据都是单块读

TABLEACCESS BY USER ROWID   直接用ROWID取得数据比如 whererowid='xxxxxx'

TABLEACCESS BY INDEX ROWID  通过索引的ROWID获得数据

 

提问:为什么通过ROWID回表是单块读??

ROWID是不是一条数据为了读一条数据读多个块合理吗??一个ROWID对应一个块

当然一个ROWID可能对应多个块行迁移

8.3 indexunique scan

INDEX UNIQUE SCAN 索引唯一扫描。单块读只可能发生在unique index/primary key等值查找

等待事件:db filesequential read但是你几乎看不到,因为只读一条数据

HINT 无需指定,有索引会自动走INDEXUNIQUE SCAN

 

OLAP这个很少见数据仓库不要主键一般不要建索引不然插入数据很慢

8.4 indexrange scan

INDEX RANGE SCAN  索引范围扫描。单块读 发生在对uniqueindex/primary key进行范围查找,对non-uniqueindex进行等值查找,范围查找

等待事件:db filesequential read如果你监控某个SQL出现大量该等待事件,有可能执行计划就有问题

HINT: INDEX(表名/别名索引名)

 

提问:索引唯一等值扫描需要几个I/O??

索引高度+1 如果存在行迁移则再+1

 

提问:非唯一索引等值扫描走什么访问路径??

不能判断是返回一条还是多条所以要走indexrange scan



节点的指针叫DBA(datablock address)

 

提问:为什么索引范围扫描是单块读??

索引是不是有root、branch、leafblock

leaf block之间是不是双向链表??在物理上是连续的吗??索引分裂就不连续了

有insert、update、delete

既然物理上存储不是连续的你能多块读吗??

 

提问:为什么indexfast full scan有能进行多块读??

索引也有段段由区组成 extent的数据块是不是连续的??

index fast full scan是根据extent来读的 这个时候肯定是多块读

只要通过双向链表扫描都是单块读

索引扫描中只有indexfast full scan才是多块读

 

是不是你们遇到过很多菜鸟拿到问题就说靠你这个都不走索引肯定慢啊

是不是有时候走索引反而更慢??是不是I/O扫描次数就多了??

SQL优化的核心思想是什么??较少物理I/O其次减少逻辑I/O

8.5 indexskip scan

exadata可以只扫描某个列smart scan

 

INDEX SKIP SCAN  索引跳跃扫描。单块读只可能发生在组合索引上,引导列(组合索引第一列)没有包含在where条件中,并且引导列基数很低。INDEXSKIP
SCAN一般来说只会返回少量数据,如果返回大量数据,说明该执行计划可能有问题,也就是说索引建立不对。

等待事件:db filesequential read

HINT: INDEX_SS(表名/别名索引名)

 

发生索引跳跃扫描的条件有哪些??

1. 必须是组合索引

2. 引导列基数很低

3. where条件中没有引导列

 

提问:为什么这里有个skip
关键字??

因为where条件里面没有引导列但还要去扫描索引

 

提问:如果where条件里有引导列那走什么??

index range scan 引导列出现在where条件中那么它怎么跳??肯定跳不了的

 

如果引导列基数很高可能就不会走indexskip scan了

提问:当执行计划中有indexskip scan还能优化吗??

直接建立一个索引不就完了干嘛非要扫描这个破索引呢??

 

select * from test where id=xx and tablespace=xx;

create index idx on test(owner,id,tablespace);

这个时候是不是可能走indexskip scan??

我直接创建这样的索引走范围扫描不就完了??

create index idx1 on test(id,tablespace);

8.6 indexfull scan

INDEX FULL SCAN 索引全扫描。单块读。它扫描的结果是有序的,因为索引是有序的。它通常发生在    

下面几种情况(注意:即使SQL满足以下情况不一定会走索引全扫描)

1.SQL语句有order by选项,并且order by的列都包含在索引中,并且order
by后列顺序必须和索引列顺序一致。

2. 在进行SORTMERGE JOIN的时候,如果要查询的列通过索引就能获得,那就不必进行全表扫描了,另外也避免了排序,因为INDEXFULL
SCAN返回的结果已经排序。

3. 当查询中有GROUP BY,并且GROUP BY的列包含在索引中。

等待事件:db file sequential read

HINT: INDEX(表名/别名索引名)

 

做个试验:order by后列顺序和索引列顺序不一致则会走 indexfast full scan

create table test as select * from dba_objects;

create index idx on test(owner,object_id);

selectowner,object_id from test where owner is not null and object_id is not nullorder by object_id,owner;







order by 选项indexfull scan是不是没有sort order by ??

分页语句就会用这种方法优化

8.7 indexfast full scan

INDEX FAST FULL SCAN 索引快速全扫描。多块读。当SQL要查询的数据能够完全从索引中获得,那么Oracle就不会走全表扫描了,就会走索引快速全扫描。索引快速全扫描类似全表扫描,它可以多块读,并且可以并行扫描。

等待事件:db filescattered read

HINT:INDEX_FFS(表名/别名索引名)

 

INDEX FAST FULL SCAN 与 TABLE ACCESS FULL一模一样的

提问:什么情况下走indexfast full scan??

这个时候是不是把索引当表用了??当表用的好处是不是扫描的体积小??是不是减少了I/O

8.8 indexrange scan descending

INDEX RANGE SCAN DESCENDING 索引降序范围扫描。单块读索引扫描默认是升序扫描,当有order by desc这种需求的时候,可能会进行索引降序范围扫描,这种情况多出现在于分页语句上。后面的案例有分页语句的优化。

等待事件:db filesquential read

HINT:INDEX_DESC(表名/别名索引名)

8.9 indexfull scan(min/max)

INDEX FULL SCAN (MIN/MAX) 索引最小/最大值扫描。单块读通常发生在 select
max(xxx) 或者select min(xxx)并且xxx列上有索引。

等待事件:db filesequential read我们几乎观察不到,因为只需读取索引高度相同的indexblock数。

HINT 无需指定,有索引会自动走INDEXFULL SCAN(MIN/MAX)

create index idd on test(object_id);

select max(object_id) from test;



select max(object_id),min(object_id) from test where object_idis not null;



是不是要进行indexfast full scan??是不是要扫描所有的indexblock??



是不是只需要访问索引的最左边或者最右边??

访问索引最左边只需要扫描索引高度这么多个块同理最右边也一样

一般来说索引高度是3那么逻辑读一般是6个

如果不改SQL
是不是要对索引的块都要扫描随着索引的块越多逻辑读越大

8.10mat_view rewrite access full

MAT_VIEW REWRITE ACCESS FULL 物化视图全表扫描。多块读当SQL查询能够直接从物化视图获得结果就会走物化视图查询。

等待事件:同全表扫描

HINT:无。通过ALTERSYSTEM/SESSION SET QUERY_REWRITE_ENABLED = TRUE/FALSE;控制

 

物化视图就当成是表不要乱建或者查询重写不要乱用

通过ALTERSYSTEM/SESSION SET QUERY_REWRITE_ENABLED=FALSE;将查询重写关掉就不会走物化视图了

为了优化A这个SQL创建了一个物化视图 A现在跑的快了物化视图会影响其他SQL

如SQL B引用了这个物化视图反而跑的更慢了因为B上走索引很快但走了物化视图物化视图上没建立索引

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐