对index直接rebuild的时候一定会是index fast full scan吗

| 4 Comments | No TrackBacks

index直接rebuild的时候一定会是index fast full scan吗?

呵呵,当然不是,我们来看一个反例:

 

SQL> create table testindex

  2  (pvalue varchar2(1),

  3   pkey number)

  4  partition by range (pkey)

  5  (

  6  partition testindex_part_1 values less than (2)

  7  tablespace TESTTBS1,

  8  partition testindex_part_2 values less than (3)

  9  tablespace TESTTBS2

 10  )

 11  enable row movement;

 

Table created

 

SQL> insert into testindex values('a',1);

 

1 row inserted

 

SQL> insert into testindex values('b',1);

 

1 row inserted

 

SQL> insert into testindex values('c',2);

 

1 row inserted

 

SQL> insert into testindex values('d',2);

 

1 row inserted

 

SQL> commit;

 

Commit complete

 

SQL> create index idx_testindex_pvalue on testindex(pvalue);

 

Index created

 

我把pvalue='a'的那条记录的pkey1改为2,这时候因为上述分区在不同的表空间下,所以索引idx_testindex_pvalue中对应于键值为'a'global rowid一定会变。

 

好了,我们来验证一下:

未改之前:

row#0[8017] flag: -----, lock: 0

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 00

row#1[8002] flag: -----, lock: 0

col 0; len 1; (1):  62

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 01

row#2[7987] flag: -----, lock: 0

col 0; len 1; (1):  63

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 00

row#3[7972] flag: -----, lock: 0

col 0; len 1; (1):  64

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 01

 

SQL> update testindex set pkey=2 where pvalue='a';

 

1 row updated

 

SQL> commit;

 

Commit complete

 

SQL> select * from testindex;

 

PVALUE       PKEY

------ ----------

b               1

c               2

d               2

a               2

 

改过之后:

row#0[8017] flag: ---D-, lock: 2

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 00

row#1[7957] flag: -----, lock: 2

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 02

row#2[8002] flag: -----, lock: 0

col 0; len 1; (1):  62

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 01

row#3[7987] flag: -----, lock: 0

col 0; len 1; (1):  63

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 00

row#4[7972] flag: -----, lock: 0

col 0; len 1; (1):  64

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 01

这里我们可以从trace文件中看到索引idx_testindex_pvalue中对于键值为'a'global rowid已经由00 01 50 dd 21 80 07 99 00 00变成了00 01 50 de 22 00 11 19 00 02

 

现在我们重建上述index,再来验证将上述index设为unusable的情况下索引idx_testindex_pvalue中对应于键值为'a'global rowid是否会变?

SQL> update testindex set pkey=1 where pvalue='a';

 

1 row updated

 

SQL> commit;

 

Commit complete

 

SQL> select * from testindex;

 

PVALUE       PKEY

------ ----------

b               1

a               1

c               2

d               2

 

SQL> drop index idx_testindex_pvalue;

 

Index dropped

 

SQL> create index idx_testindex_pvalue on testindex(pvalue);

 

Index created

 

未改之前:

row#0[8017] flag: -----, lock: 0

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 02

row#1[8002] flag: -----, lock: 0

col 0; len 1; (1):  62

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 01

row#2[7987] flag: -----, lock: 0

col 0; len 1; (1):  63

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 00

row#3[7972] flag: -----, lock: 0

col 0; len 1; (1):  64

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 01

 

SQL> alter index idx_testindex_pvalue unusable;

 

Index altered

 

SQL> update testindex set pkey=2 where pvalue='a';

 

update testindex set pkey=2 where pvalue='a'

 

ORA-01502: index 'DRAS.IDX_TESTINDEX_PVALUE' or partition of such index is in unusable state

 

SQL> ALTER SESSION SET SKIP_UNUSABLE_INDEXES = TRUE;

 

Session altered

 

SQL> update testindex set pkey=2 where pvalue='a';

 

1 row updated

 

SQL> commit;

 

Commit complete

 

SQL> select * from testindex;

 

PVALUE       PKEY

------ ----------

b               1

c               2

d               2

a               2

 

改过之后:

row#0[8017] flag: -----, lock: 0

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 02

row#1[8002] flag: -----, lock: 0

col 0; len 1; (1):  62

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 01

row#2[7987] flag: -----, lock: 0

col 0; len 1; (1):  63

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 00

row#3[7972] flag: -----, lock: 0

col 0; len 1; (1):  64

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 01

可以从结果里看到,这时候当我将上述index设为unusable的情况下索引idx_testindex_pvalue中对应于键值为'a'global rowid没有变!

 

这时候如果我们rebuild online的话是能修正上述错误的,因为rebuild online走的是全表扫描。但是如果我们只是rebuild,因为rebuild走的是index fast full scan那这里oracle能正确的修正上述global rowid的错误吗?我们来验证一下:

SQL> alter index idx_testindex_pvalue rebuild;

 

Index altered

 

rebuild之后:

row#0[8017] flag: -----, lock: 0

col 0; len 1; (1):  61

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 03

row#1[8002] flag: -----, lock: 0

col 0; len 1; (1):  62

col 1; len 10; (10):  00 01 50 dd 21 80 07 99 00 01

row#2[7987] flag: -----, lock: 0

col 0; len 1; (1):  63

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 00

row#3[7972] flag: -----, lock: 0

col 0; len 1; (1):  64

col 1; len 10; (10):  00 01 50 de 22 00 11 19 00 01

从结果里我们可以看到,即便我这里用的是rebuildoracle这里也已经将上述global rowid的错误修正。

 

为什么会这样?

很简单,因为在indexunusable的情况下,即使是直接rebuildoracle这里也会走全表扫描。

SQL> select status from dba_indexes where index_name='IDX_TESTINDEX_PVALUE';

 

STATUS

--------

VALID

 

SQL> explain plan for alter index idx_testindex_pvalue rebuild;

 

Explained

 

SQL> select * from table(dbms_xplan.display);

 

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

| Id  | Operation              |  Name                 | Rows  | Bytes | Cost  |

--------------------------------------------------------------------------------

|   0 | ALTER INDEX STATEMENT  |                       |  9802 | 19604 |    13 |

|   1 |  INDEX BUILD NON UNIQUE| IDX_TESTINDEX_PVALUE  |       |       |       |

|   2 |   SORT CREATE INDEX    |                       |  9802 | 19604 |       |

|   3 |    INDEX FAST FULL SCAN| IDX_TESTINDEX_PVALUE  |  9802 | 19604 |       |

--------------------------------------------------------------------------------

Note: cpu costing is off, PLAN_TABLE' is old version

 

11 rows selected

 

SQL> alter index idx_testindex_pvalue unusable;

 

Index altered

 

SQL> select status from dba_indexes where index_name='IDX_TESTINDEX_PVALUE';

 

STATUS

--------

UNUSABLE

 

SQL> explain plan for alter index idx_testindex_pvalue rebuild;

 

Explained

 

SQL> select * from table(dbms_xplan.display);

 

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

| Id  | Operation              |  Name                 | Rows  | Bytes | Cost  |

--------------------------------------------------------------------------------

|   0 | ALTER INDEX STATEMENT  |                       |  9802 | 19604 |    13 |

|   1 |  INDEX BUILD NON UNIQUE| IDX_TESTINDEX_PVALUE  |       |       |       |

|   2 |   SORT CREATE INDEX    |                       |  9802 | 19604 |       |

|   3 |    PARTITION RANGE ALL |                       |       |       |       |

|   4 |     TABLE ACCESS FULL  | TESTINDEX             |  9802 | 19604 |    13 |

--------------------------------------------------------------------------------

Note: cpu costing is off, PLAN_TABLE' is old version

 

12 rows selected

 

No TrackBacks

TrackBack URL: http://dbsnake.com/cgi-bin/mt/mt-tb.cgi/50

4 Comments

实验很有趣。
index unused 就说明index 数据可能是不正确的,rebuild,或者online 自然都要从表中重整index block 咯

另外explain for ddl 有可能不准确

谢谢提醒:)
这个反例是我特意构造出来的,只是想看一看oracle在索引有问题的情况下的表现。

rebuild index online也是走的全表扫描,而不是从索引扫描。

熊哥,我在文中提到“这时候如果我们rebuild online的话是能修正上述错误的,因为rebuild online走的是全表扫描”,咱们的观点是一致的呀。

Leave a comment

Recent Comments

  • cui hua: 熊哥,我在文中提到“这时候如果我们rebuild online的话是能修正上述错误的,因为rebuild online走的是全表扫描”,咱们的观点是一致的呀。 read more
  • 老熊: rebuild index online也是走的全表扫描,而不是从索引扫描。 read more
  • cui hua: 谢谢提醒:) 这个反例是我特意构造出来的,只是想看一看oracle在索引有问题的情况下的表现。 read more
  • hoterran: 实验很有趣。 index unused 就说明index 数据可能是不正确的,rebuild,或者online 自然都要从表中重整index block 咯 另外explain for read more

About this Entry

This page contains a single entry by cui hua published on June 30, 2009 1:09 PM.

当无统计信息的时候ix_sel的值取决于什么 was the previous entry in this blog.

2009年年中总结 is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.