[20170209]索引范围访问2.txt

[20170209]索引范围访问2.txt

--ITPUB网友问的问题:

http://www.itpub.net/thread-2083504-1-1.html
--索引范围扫描是如何访问数据块的?
1 FOR  (根节点-> 分支节点->叶节点->表) 这循环吗?
2 还是(根节点-> 分支节点->叶节点->叶节点->叶节点->叶节点->表)?
3 还是 (根节点-> 分支节点->叶节点->表->叶节点->表->叶节点->表->叶节点->表)?

--我认为是3,还是测试来说明问题:

1.环境:
SCOTT@book> @ &r/ver1
PORT_STRING         VERSION        BANNER
------------------- -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx 11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

create table t (id number,v1 varchar2(20),v2 varchar2(4000),v3 varchar2(3000));
insert into t as select rownum ,rownum||'aaaa',lpad('a',4000,'a'),lpad('b',3000,'b') from dual connect by level<=200;
commit ;
create unique index i_t_id on t(id) pctfree 80;
--分析略.

SCOTT@book> column PARTITION_NAME noprint
SCOTT@book> select * from dba_extents where file_id=4 and segment_name in ('T','I_T_ID');
OWNER  SEGMENT_NAME SEGMENT_TYPE TABLESPACE_NAME EXTENT_ID FILE_ID BLOCK_ID   BYTES BLOCKS RELATIVE_FNO
------ ------------ ------------ --------------- --------- ------- -------- ------- ------ ------------
SCOTT  I_T_ID       INDEX        USERS                   0       4     1200   65536      8            4
SCOTT  T            TABLE        USERS                   0       4      816   65536      8            4
SCOTT  T            TABLE        USERS                   1       4      824   65536      8            4
SCOTT  T            TABLE        USERS                   2       4      832   65536      8            4
SCOTT  T            TABLE        USERS                   3       4      840   65536      8            4
SCOTT  T            TABLE        USERS                   4       4      848   65536      8            4
SCOTT  T            TABLE        USERS                   5       4      856   65536      8            4
SCOTT  T            TABLE        USERS                   6       4      864   65536      8            4
SCOTT  T            TABLE        USERS                   7       4      872   65536      8            4
SCOTT  T            TABLE        USERS                   8       4      880   65536      8            4
SCOTT  T            TABLE        USERS                   9       4      888   65536      8            4
SCOTT  T            TABLE        USERS                  10       4     1152   65536      8            4
SCOTT  T            TABLE        USERS                  11       4     1160   65536      8            4
SCOTT  T            TABLE        USERS                  12       4     1168   65536      8            4
SCOTT  T            TABLE        USERS                  13       4     1176   65536      8            4
SCOTT  T            TABLE        USERS                  14       4     1184   65536      8            4
SCOTT  T            TABLE        USERS                  15       4     1192   65536      8            4
SCOTT  T            TABLE        USERS                  16       4     1280 1048576    128            4
18 rows selected.

SCOTT@book> select object_name,object_id,data_object_id from dba_objects where owner=user and  object_name in ('T','I_T_ID');
OBJECT_NAME           OBJECT_ID DATA_OBJECT_ID
-------------------- ---------- --------------
I_T_ID                    89842          89842   <==0x15ef2
T                         89841          89841   <==0x15ef1

SCOTT@book> select segment_name,header_file,header_block from dba_segments where segment_name in ('T','I_T_ID');
SEGMENT_NAME         HEADER_FILE HEADER_BLOCK
-------------------- ----------- ------------
T                              4          818
I_T_ID                         4         1202

--这样基本1条记录1块.

SCOTT@book> alter session set events 'immediate trace name treedump level 89842';
Session altered.

*** 2017-02-09 15:02:47.723
branch: 0x10004b3 16778419 (0: nrow: 2, level: 1)          => dba=4,1203
   leaf: 0x10004b4 16778420 (-1: nrow: 111 rrow: 111)      => dba=4,1204
   leaf: 0x10004b5 16778421 (0: nrow: 89 rrow: 89)         => dba=4,1205
----- end tree dump
--//索引记录分部在2块.

2.测试:
SCOTT@book> alter session set statistics_level=all;
Session altered.

SCOTT@book> show arraysize
arraysize 200

SCOTT@book> select /*+ index( t i_t_id ) */ id,v1 from t where id between 101 and 120;
ID V1
--- --------------------
101 101aaaa
102 102aaaa
103 103aaaa
104 104aaaa
105 105aaaa
106 106aaaa
107 107aaaa
108 108aaaa
109 109aaaa
110 110aaaa
111 111aaaa
112 112aaaa
113 113aaaa
114 114aaaa
115 115aaaa
116 116aaaa
117 117aaaa
118 118aaaa
119 119aaaa
120 120aaaa
20 rows selected.

SCOTT@book> @ &r/dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  cx4u60mg16ksy, child number 0
-------------------------------------
select /*+ index( t i_t_id ) */ id,v1 from t where id between 101 and 120
Plan hash value: 4153437776
--------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |      1 |        |       |    24 (100)|          |     20 |00:00:00.01 |      24 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T      |      1 |     21 |   252 |    24   (0)| 00:00:01 |     20 |00:00:00.01 |      24 |
|*  2 |   INDEX RANGE SCAN          | I_T_ID |      1 |     21 |       |     2   (0)| 00:00:01 |     20 |00:00:00.01 |       4 |
--------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T@SEL$1
   2 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ID">=101 AND "ID"<=120)
26 rows selected.
--//逻辑读是24. (arraysize=200)

SCOTT@book> set array 2
SCOTT@book> select /*+ index( t i_t_id ) */ id,v1 from t where id between 101 and 120;
...
Plan hash value: 4153437776
--------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |      1 |        |       |    24 (100)|          |     20 |00:00:00.01 |      32 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T      |      1 |     21 |   252 |    24   (0)| 00:00:01 |     20 |00:00:00.01 |      32 |
|*  2 |   INDEX RANGE SCAN          | I_T_ID |      1 |     21 |       |     2   (0)| 00:00:01 |     20 |00:00:00.01 |      12 |
--------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
   1 - SEL$1 / T@SEL$1
   2 - SEL$1 / T@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ID">=101 AND "ID"<=120)
--//逻辑读是24. (arraysize=2)

3.跟踪看看:
--//如何跟踪逻辑读,想了N久才想起来10200事件.
$ oerr ora 10200
10200, 00000, "consistent read buffer status"
// *Cause:
// *Action:

SCOTT@book> ALTER SESSION SET EVENTS '10200 TRACE NAME CONTEXT FOREVER, LEVEL 1';
Session altered.

SCOTT@book> select /*+ index( t i_t_id ) */ id,v1 from t where id between 101 and 120;
        ID V1
---------- --------------------
       101 101aaaa
...
       120 120aaaa

20 rows selected.

SCOTT@book> ALTER SESSION SET EVENTS '10200 TRACE NAME CONTEXT OFF';
Session altered.

--//检查转储:
ktrgtc2(): started for block <0x0004 : 0x010004b3> objd: 0x00015ef2
  env [0x7fadbb8f6fdc]: (scn: 0x0003.175073c2  xid: 0x0000.000.00000000  uba: 0x00000000.0000.00  statement num=0  parent xid: 0x0000.000.00000000  st-scn: 0x0000.00000000  hi-scn: 0x0000.00000000  ma-scn: 0x0003.1750734b  flg: 0x00000661)
ktrexc(): returning 2 on:  0xc0f4928  cr-scn: 0xffff.ffffffff  xid: 0x0000.000.00000000  uba: 0x00000000.0000.00  cl-scn: 0xffff.ffffffff  sfl: 0
ktrgtc2(): completed for block <0x0004 : 0x010004b3> objd: 0x00015ef2
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2
env [0x7fadbb8f6fdc]: (scn: 0x0003.175073c2  xid: 0x0000.000.00000000  uba: 0x00000000.0000.00  statement num=0  parent xid: 0x0000.000.00000000  st-scn: 0x0000.00000000  hi-scn: 0x0000.00000000  ma-scn: 0x0003.1750734b  flg: 0x00000660)
ktrexf(): returning 9 on:  0xc0f4928  cr-scn: 0xffff.ffffffff  xid: 0x0000.000.00000000  uba: 0x00000000.0000.00  cl-scn: 0xffff.ffffffff  sfl: 0
ktrgcm(): completed for block  <0x0004 : 0x010004b4> objd: 0x00015ef2
ktrget3(): completed for  block <0x0004 : 0x010004b4> objd: 0x00015ef2
ktrget2(): started for block  <0x0004 : 0x0100049f> objd: 0x00015ef1

$ grep "started" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_53991.trc|wc
     32     288    2207
--//正好对上.

$ grep "started" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_53991.trc
ktrgtc2(): started for block <0x0004 : 0x010004b3> objd:  0x00015ef2    <= dba=4,1203,索引的根节点块
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2    <= dba=4,1204,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x0100049f> objd: 0x00015ef1    <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2    <= dba=4,1204,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x01000498> objd: 0x00015ef1    <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x01000499> objd: 0x00015ef1    <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2    <= dba=4,1204,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x010004a6> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004a7> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2
ktrget2(): started for block  <0x0004 : 0x010004a1> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004a4> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2
ktrget2(): started for block  <0x0004 : 0x010004a5> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004a2> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2
ktrget2(): started for block  <0x0004 : 0x010004a3> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004aa> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004b5> objd: 0x00015ef2
ktrget2(): started for block  <0x0004 : 0x010004ab> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004ac> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004b5> objd: 0x00015ef2
ktrget2(): started for block  <0x0004 : 0x010004ad> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004ae> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004b5> objd: 0x00015ef2
ktrget2(): started for block  <0x0004 : 0x010004af> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004a8> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004b5> objd: 0x00015ef2
ktrget2(): started for block  <0x0004 : 0x010004a9> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x0100055a> objd: 0x00015ef1
ktrget2(): started for block  <0x0004 : 0x010004b5> objd: 0x00015ef2
ktrget2(): started for block  <0x0004 : 0x0100055e> objd: 0x00015ef1

--//仔细看后面的规律都是
--//先访问0x00015ef2对象一次,再访问0x00015ef1对象2次.我注解在后面.
--//你可以注意一个小细节,第一次读表是读一条记录.可以看看我以前写的帖子:
http://blog.itpub.net/267265/viewspace-1430902/

--//设置为3重复测试看看.
SCOTT@book> set array 3
SCOTT@book> ALTER SESSION SET EVENTS '10200 TRACE NAME CONTEXT FOREVER, LEVEL 1';
SCOTT@book> select /*+ index( t i_t_id ) */ id,v1 from t where id between 101 and 120;
Plan hash value: 4153437776
--------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |      1 |        |       |    24 (100)|          |     20 |00:00:00.01 |      30 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T      |      1 |     21 |   252 |    24   (0)| 00:00:01 |     20 |00:00:00.01 |      30 |
|*  2 |   INDEX RANGE SCAN          | I_T_ID |      1 |     21 |       |     2   (0)| 00:00:01 |     20 |00:00:00.01 |      10 |
--------------------------------------------------------------------------------------------------------------------------------
SCOTT@book> ALTER SESSION SET EVENTS '10200 TRACE NAME CONTEXT OFF';

$ grep "started" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_54066.trc|wc
     30     270    2069
--//也执行计划看到的逻辑读一致.

$ grep "started" /u01/app/oracle/diag/rdbms/book/book/trace/book_ora_54066.trc
ktrgtc2(): started for block <0x0004 : 0x010004b3> objd: 0x00015ef2       <= dba=4,1203,索引的根节点块
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2      <= dba=4,1204,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x0100049f> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2      <= dba=4,1204,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x01000498> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x01000499> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004a6> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2      <= dba=4,1204,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x010004a7> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004a1> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004a4> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2      <= dba=4,1204,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x010004a5> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004a2> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004a3> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004b4> objd: 0x00015ef2      <= dba=4,1204,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x010004aa> objd: 0x00015ef1      <= 读表段一条记录 ,注意这里仅仅剩下1条记录. 也就是前面分支仅仅11个键值.
ktrget2(): started for block  <0x0004 : 0x010004b5> objd: 0x00015ef2      <= dba=4,1205,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x010004ab> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004ac> objd: 0x00015ef1      <= 读表段一条记录,注意这里仅仅访问2条,因为arraysize=3.
ktrget2(): started for block  <0x0004 : 0x010004b5> objd: 0x00015ef2      <= dba=4,1205,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x010004ad> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004ae> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004af> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004b5> objd: 0x00015ef2      <= dba=4,1205,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x010004a8> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004a9> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x0100055a> objd: 0x00015ef1      <= 读表段一条记录
ktrget2(): started for block  <0x0004 : 0x010004b5> objd: 0x00015ef2      <= dba=4,1205,索引的叶子块
ktrget2(): started for block  <0x0004 : 0x0100055e> objd: 0x00015ef1      <= 读表段一条记录

时间: 2024-10-18 11:17:40

[20170209]索引范围访问2.txt的相关文章

[20150803]使用函数索引注意的问题.txt

[20150803]使用函数索引注意的问题.txt --昨天在10g下优化时遇到一个奇怪的问题,做一个记录: --首先说明一下,最近一段时间在做一个项目的优化,这个项目实际上ETL项目: http://baike.baidu.com/link?url=OlbL-2LIVu06toxpf5-PxgekWlOtRgrdwPhGYNx9TgCnCC5WdAGiwOWQXcfUbujcUNwUU6ojdanwP1wSbC_Vf95sgbq7PonHaEZWBVrqkQm ETL,是英文 Extract-

[20121028]IOT的第2索引-NULL的问题.txt

[20121028]IOT的第2索引-NULL的问题.txt IOT表实际上时索引结构,如果第2索引的键值为NULL,会是什么情况呢? 因为第2索引包含主键,而主键是不能为NULL的,这样即使第2索引的键值为NULL,会包括在第2索引中吗? 自己做一些测试验证看看: 1.测试环境: SQL> select * from v$version where rownum BANNER -----------------------------------------------------------

[20120509]IOT索引组织表相关信息的学习(三).txt

[20120509]IOT索引组织表相关信息的学习(三).txt 上次链接:http://space.itpub.net/267265/viewspace-719517http://space.itpub.net/267265/viewspace-717272 IOT 是一种特殊的索引结构,使用它能够解决特定场合的应用问题,但是在许多应用中很少使用,更多的是使用堆表.我仅仅在生产系统中对3个表使用,我偏向使用静态以及"只读"的小表. 如果IOT表存在除主键外的第2索引,如果使用它存在物

用索引器简化的C#类型信息访问

"C#中的Indexer给人一种更'透彻'的感觉,集合类型就是集合类型,有自己专用但又最简洁的访问方式,而且同一类型可以有不同的索引访问方式."    --<设计模式_基于C#的工程化实现及扩展> 示例代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace BangWorks.PractcalPattern.Concept.Inder

根据 Dictionary 编写了个非重复的,可按索引访问的,可快速查找的,NonDupList

问题描述 有没有同样需求的,可以找我咨询.准备写一篇博客,以解析Dictionary内部的实现代码,并会附上我这个NonDupList源码 解决方案 解决方案二:非重复.可快速查找没看出是什么意思.解决方案三:原理不就是链表吗?解决方案四:重复造车....解决方案五:非重复的,可按索引访问的,可快速查找的这个跟Dictionary有什么区别呢?解决方案六:Dictionary具有如下特性:压缩了hash值范围,并基本上按Array一样访问元素,自适应元素的数量我们假定有这样一个结构体:struc

Sphinx全文检索引擎使用指南:索引配置选项

8.2.1. type 索引类型.可选选项,默认值为空(索引为简单本地索引).可用的值包括空字符串或 "distributed" Sphinx支持两种不同的索引类型:本地--在本机上存储和处理,和远程--不仅涉及http://www.aliyun.com/zixun/aggregation/20263.html">本地搜索,而且同时通过网络向远程searchd实力做查询.索引类似选项使您可以选择使用何种索引.索引默认是本地型.指定"distributed&qu

使用索引的误区之五:空值的妙用

索引 使用索引的误区之五:空值的妙用并不是因为完全为空的条目不被记录到索引中,就坚决不能使用空值,相反,有时候合理使用oracle的空值会为我们的查询带来几倍甚至几十倍的效率提高. 举个例子,加入有一个表,里面有个字段是"处理时间",如果没有处理的事务,该列就为空,并且在大部分情况下,处理的事务总是在总记录数的10%或者更少,而等待处理的记录("处理时间"这列为空)总是绝大多数的记录,那么在"等待时间"这列上建立索引,索引中就总是会保存很少的记录

索引全攻略

攻略|索引 索引问题 一 概述    可以利用索引快速访问数据库表中的特定信息.索引是对数据库表中一个或多个列的值进行排序的结构.   索引提供指针以指向存储在表中指定列的数据值,然后根据指定的排序次序排列这些指针.   数据库使用索引的方式与使用书的目录很相似:通过搜索索引找到特定的值,   然后跟随指针到达包含该值的行 二 索引的两种类型: 聚集索引=簇集索引 聚集索引基于数据行的键值在表内排序和存储这些数据行.由于数据行按基于聚集索引键的排序次序存储,因此聚集索引对查找行很有效.每个表只能

ASP.NET2.0数据操作之创建数据访问层(1)

asp.net|创建|访问|数据 导言 作为web开发人员,我们的生活围绕着数据操作.我们建立数据库来存储数据,写编码来访问和修改数据,设计网页来采集和汇总数据.本文是研究在ASP.NET 2.0中实现这些常见的数据访问模式之技术的长篇系列教程的第一篇.我们将从创建一个软件框架开始,这个框架的组成部分包括一个使用强类型的DataSet的数据访问层(DAL),一个实施用户定义的业务规则的业务逻辑层(BLL),以及一个由共享页面布局的ASP.NET网页组成的表现层.在打下这个后端的基础工作之后,我们