SQL> select count(*) from test_idx; COUNT(*) ---------- 19087751 SQL> select segment_name,segment_type,bytes/1024/1024 as MB from user_segments where segment_name='TEST_IDX'; SEGMENT_NAME SEGMENT_TYPE MB ------------------------------ ------------------ ---------- TEST_IDX TABLE 2176 SQL> select username,default_tablespace from dba_users where username='SCOTT'; USERNAME DEFAULT_TABLESPACE ------------------------------ ------------------------------ SCOTT USERS SQL> select index_name,tablespace_name from user_indexes where index_name='TEST_IDX_IDX1'; INDEX_NAME TABLESPACE_NAME ------------------------------ ------------------------------ TEST_IDX_IDX1 USERS SQL> SQL> SQL> SQL> select * from test_idx where object_name='I_USER1' AND object_id=46; 263 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 4118933773 --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 263 | 54441 | 267 (0)| 00:00:04 | | 1 | TABLE ACCESS BY INDEX ROWID| TEST_IDX | 263 | 54441 | 267 (0)| 00:00:04 | |* 2 | INDEX RANGE SCAN | TEST_IDX_IDX1 | 263 | | 5 (0)| 00:00:01 | --------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("OBJECT_ID"=46 AND "OBJECT_NAME"='I_USER1') Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 11 recursive calls 0 db block gets 517 consistent gets 260 physical reads 9304 redo size 24860 bytes sent via SQL*Net to client 606 bytes received via SQL*Net from client 19 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 263 rows processed rebuild 索引; SQL> select * from v$mystat where rownum<2; SID STATISTIC# VALUE ---------- ---------- ---------- 34 0 0 SQL> alter index TEST_IDX_IDX1 rebuild tablespace example; SQL> select * from v$mystat where rownum<2; SID STATISTIC# VALUE ---------- ---------- ---------- 58 0 0 SQL> insert into test_idx(object_name) values('USERS'); 此时SESSION 被堵塞 SQL> select * from v$lock where type in ('TM','TX'); ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- 0056BAB0 0056BAE0 34 TM 74914 0 4 0 210 1 0056BAB0 0056BAE0 58 TM 74914 0 0 3 107 0 0056BAB0 0056BAE0 59 TM 5003 0 3 0 379 0 2C361C24 2C361C64 59 TX 131081 1331 6 0 378 0 SQL> select object_name from dba_objects where object_id=74914; OBJECT_NAME ------------------------------------------------------------------- TEST_IDX 索引仍旧能正常使用: SQL> SQL> select * from test_idx where object_name='I_USER1' AND object_id=46; 263 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 4118933773 --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 263 | 54441 | 267 (0)| 00:00:04 | | 1 | TABLE ACCESS BY INDEX ROWID| TEST_IDX | 263 | 54441 | 267 (0)| 00:00:04 | |* 2 | INDEX RANGE SCAN | TEST_IDX_IDX1 | 263 | | 5 (0)| 00:00:01 | --------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("OBJECT_ID"=46 AND "OBJECT_NAME"='I_USER1') Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 185 recursive calls 0 db block gets 414 consistent gets 0 physical reads 0 redo size 24860 bytes sent via SQL*Net to client 606 bytes received via SQL*Net from client 19 SQL*Net roundtrips to/from client 6 sorts (memory) 0 sorts (disk) 263 rows processed 那么插入insert into test_idx(object_name,object_id) values('USERS',100); 也被堵塞 插入insert into test_idx(owner) values('USERS'); 也被堵住 原因重建索引的时候会对表加LMODE=4的锁,会给表加上4 - share (S) 会阻止其他SESSION 对表的一切DML操作。 在线重建呢? SQL> select * from v$mystat where rownum<2; SID STATISTIC# VALUE ---------- ---------- ---------- 55 0 0 SQL> alter index TEST_IDX_IDX1 rebuild tablespace USERS online; SQL> select * from v$lock where type in ('TM','TX'); ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- 00A94A48 00A94A78 55 TM 74914 0 2 0 9 0 00A94A48 00A94A78 55 TM 74918 0 4 0 4 0 2B834F74 2B834FB4 55 TX 65552 997 6 0 4 0 SQL> select object_name from dba_objects where object_Id in (74914,74918); OBJECT_NAME -------------------------------------------------------------------------------------------------------------------------------- TEST_IDX SYS_JOURNAL_74915 把LMODE=4加在了SYS_JOURNAL_74915上 rebulid online的是受会产生一个SYS_JOURNAL_74915的IOT类型的系统临时表,所有rebuild online的索引变化都记录在这个表中,当新的索引创建完后,把这个表的记录 维护到索引中 此时DML有影响吗? SQL> insert into test_idx(object_name,object_id) values('USERS',100); 1 row created. SQL> commit; Commit complete. 此时DML没有影响 SQL> select * from test_idx where object_name='CZCB' and object_id=9999; no rows selected SQL> insert into test_idx(object_name,object_id) values('CZCB','9999');SQL> 1 row created. SQL> commit; Commit complete. SQL> set linesize 200 SQL> set pagesixze 200 SP2-0158: unknown SET option "pagesixze" SQL> set pagesize 200 SQL> set autot trace * SQL> select * from test_idx where object_name='CZCB' and object_id=9999; Execution Plan ---------------------------------------------------------- Plan hash value: 4118933773 --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 207 | 5 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| TEST_IDX | 1 | 207 | 5 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | TEST_IDX_IDX1 | 1 | | 4 (0)| 00:00:01 | --------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("OBJECT_ID"=9999 AND "OBJECT_NAME"='CZCB') Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 7 recursive calls 0 db block gets 109 consistent gets 0 physical reads 80 redo size 1329 bytes sent via SQL*Net to client 419 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed 之前object_name='CZCB' and object_id=9999;记录不存在索引中,为什么新插入的还能走索引呢? 重建索引完成后: SQL> SQL> SQL> SQL> SQL> SQL> select object_name from dba_objects where object_Id in (74914,74918); OBJECT_NAME -------------------------------------------------------------------------------- TEST_IDX SQL> set linesize 200 SQL> set pagesize 200 SQL> select object_name,object_id from test_idx where object_name='AOBAMCCCBBBBCA' and object_id=8888; no rows selected SQL> insert into test_idx(object_name,object_id) values('AOBAMCCCBBBBCA','8888'); 1 row created. SQL> commit; Commit complete. SQL> select object_name,object_id from test_idx where object_name='AOBAMCCCBBBBCA' and object_id=8888; OBJECT_NAME OBJECT_ID -------------------------------------------------------------------------------------------------------------------------------- ---------- AOBAMCCCBBBBCA 8888 SQL> set linesize 200 SQL> set pagesixe 200 SP2-0158: unknown SET option "pagesixe" SQL> set pagesize 200 SQL> set autot trace SQL> select object_name,object_id from test_idx where object_name='AOBAMCCCBBBBCA' and object_id=8888; Execution Plan ---------------------------------------------------------- Plan hash value: 644446973 ---------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 79 | 4 (0)| 00:00:01 | |* 1 | INDEX RANGE SCAN| TEST_IDX_IDX1 | 1 | 79 | 4 (0)| 00:00:01 | ---------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("OBJECT_ID"=8888 AND "OBJECT_NAME"='AOBAMCCCBBBBCA') Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 5 consistent gets 0 physical reads 0 redo size 504 bytes sent via SQL*Net to client 419 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed 在线重建索引过程中,插入新的数据(之前表和索引中不存在的),都可以直接从索引返回,Oracle你也太牛逼了。 在线重建索引期间索引仍旧可用,不影响DML操作