ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 索引组织表中逻辑ROWID的物理猜(二)

索引组织表中逻辑ROWID的物理猜(二)

原创 Linux操作系统 作者:yangtingkun 时间:2009-01-20 21:54:12 0 删除 编辑

第一次看CONCEPT的时候,一直不是很明白,Oracle索引组织表中逻辑ROWID的物理猜是如何实现的,而这次看的时候很自然的就想明白其中的实现。

索引组织表中逻辑ROWID的物理猜:http://yangtingkun.itpub.net/post/468/477286

通过一个具体的例子简单描述一下物理猜的过程。

 

 

可能有人对这个概念不是很理解,通过一个小例子,说明一下索引组织表如何根据第二索引来访问数据的。

SQL> CREATE TABLE T_INDEX_ORG
  2  (ID NUMBER PRIMARY KEY,
  3  NAME VARCHAR2(30),
  4  TYPE VARCHAR2(18))
  5  ORGANIZATION INDEX;

表已创建。

SQL> CREATE INDEX IND_INDEX_ORG_NAME ON T_INDEX_ORG (NAME);

索引已创建。

SQL> INSERT INTO T_INDEX_ORG VALUES (0, 'FIRST', 'TEST');

已创建 1 行。

SQL> INSERT INTO T_INDEX_ORG
  2  SELECT ROWNUM, OBJECT_NAME, OBJECT_TYPE
  3  FROM DBA_OBJECTS
  4  WHERE ROWNUM < 1000;

已创建999行。

SQL> COMMIT;

提交完成。

建立了一个索引组织表,并插入一些记录。每条记录的插入的同时会将当时的物理位置存储在逻辑ROWID中,作为物理猜的基础。对于第一条插入的语句而言,随后的插入会导致索引组织表不断进行调整,因此在后一个插入完成时,第一次插入的记录已经不在开始的位置,这时物理猜就不会准确,而会导致额外的主键扫描。而第二次插入的记录,逻辑ROWID记录的位置就是这条记录的真实位置,因此不会导致物理猜,下面看看二者访问时逻辑读是否有差异:

SQL> SELECT * FROM T_INDEX_ORG WHERE ID = 0;

        ID NAME                           TYPE
---------- ------------------------------ ------------------
         0 FIRST                          TEST

SQL> SELECT * FROM T_INDEX_ORG WHERE ID = 999;

        ID NAME                           TYPE
---------- ------------------------------ ------------------
       999 V$SORT_SEGMENT                 SYNONYM

SQL> SET AUTOT ON
SQL> SELECT * FROM T_INDEX_ORG
  2  WHERE NAME = 'FIRST';

        ID NAME                           TYPE
---------- ------------------------------ ------------------
         0 FIRST                          TEST


执行计划
----------------------------------------------------------
   0      SELECT STATEMENT ptimizer=CHOOSE (Cost=3 Card=1 Bytes=41)
   1    0   INDEX (UNIQUE SCAN) OF 'SYS_IOT_TOP_32243' (UNIQUE) (Cost=1 Card=1 Bytes=41)
   2    1     INDEX (RANGE SCAN) OF 'IND_INDEX_ORG_NAME' (NON-UNIQUE) (Cost=1 Card=1)

 


统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          6  consistent gets
          0  physical reads
          0  redo size
        484  bytes sent via SQL*Net to client
        372  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> SELECT * FROM T_INDEX_ORG
  2  WHERE NAME = 'V$SORT_SEGMENT';

        ID NAME                           TYPE
---------- ------------------------------ ------------------
       999 V$SORT_SEGMENT                 SYNONYM


执行计划
----------------------------------------------------------
   0      SELECT STATEMENT ptimizer=CHOOSE (Cost=3 Card=1 Bytes=41)
   1    0   INDEX (UNIQUE SCAN) OF 'SYS_IOT_TOP_32243' (UNIQUE) (Cost=1 Card=1 Bytes=41)
   2    1     INDEX (RANGE SCAN) OF 'IND_INDEX_ORG_NAME' (NON-UNIQUE) (Cost=1 Card=1)

 


统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
        498  bytes sent via SQL*Net to client
        372  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

可以看到,虽然二者的执行计划完全一样,但是物理猜没有命中,导致额外的主键扫描会增加逻辑IO,这个例子就增加了2次逻辑IO

SQL> SELECT ROWID, ID, NAME FROM T_INDEX_ORG
  2  WHERE NAME IN ('FIRST', 'V$SORT_SEGMENT');

ROWID                                             ID NAME
----------------------------------------- ---------- ------------------------------
*BAJAABwBgP4                                       0 FIRST
*BAJAAB4Dwgpk/g                                  999 V$SORT_SEGMENT


执行计划
----------------------------------------------------------
   0      SELECT STATEMENT ptimizer=CHOOSE (Cost=2 Card=1 Bytes=47)
   1    0   INLIST ITERATOR
   2    1     INDEX (RANGE SCAN) OF 'IND_INDEX_ORG_NAME' (NON-UNIQUE) (Cost=2 Card=1 Bytes=47)

 


统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          5  consistent gets
          0  physical reads
          0  redo size
        557  bytes sent via SQL*Net to client
        372  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed

顺便提一句,由于索引组织表包含的ROWID信息为逻辑ROWID,而逻辑ROWID有包含了主键信息,所以上面这个包含了ROWID、主键和索引列的查询,仅通过索引扫描就可以实现,而不需要再扫描主键了。

 

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-541559/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
暂无介绍

注册时间:2007-12-29

  • 博文量
    1955
  • 访问量
    10524847