oracle超大表建索引,Oracle 大表创建索引

有个2亿记录的表,发现需要添加一个联合索引,结果就采用普通的create index index_name on tablename (entp_id,sell_date),结果悲剧了,把所有的DML语句都阻塞了,导致系统不能正常使用,还好是晚上10点,用户不是非常多,1个小时候,索引结束,阻塞解决;上网查了一下,如果加上 online参数后,就可以在线做索引,而不需要阻塞所有的DML语句,血的教训,拿出来与各位共勉,

创建测试表

create table t_test

(

col1 number,

col2 number

);

造测试数据(根据自己机器具体情况估计需要的数据量,使创建索引的时间大概在20-30秒)

insert into t_test

select rownum col1, rownum col2 from dual

connect by rownum<10000000;

commit;

create index

会话1:

SQL> set time on

10:22:01 SQL> set timing on

10:22:02 SQL>

--获取 会话1 sid

10:22:04 SQL> select sid from v$mystat where rownum=1;

SID

144

Elapsed: 00:00:00.01

会话2:

SQL> set time on

10:22:06 SQL> set timing on

10:22:06 SQL>

--获取 会话2 sid

10:22:06 SQL> select sid from v$mystat where rownum=1;

SID

147

Elapsed: 00:00:00.01

会话3:

SQL> set time on

10:22:11 SQL> set timing on

10:22:11 SQL>

--格式化输出

10:22:13 SQL> set line 200

10:23:03 SQL> col addr for a10

10:23:03 SQL> col kaddr for a10

10:23:03 SQL> col sid for 999999

10:23:03 SQL> col type for a10

10:23:03 SQL> col id1 for 99999999999

10:23:03 SQL> col id2 for 99999999999

10:23:03 SQL> col lmod for 99

10:23:03 SQL> col request for 99

10:23:03 SQL> col ctime for 999999

10:23:03 SQL> col block for 99

10:23:03 SQL> col table_name for a30

10:23:03 SQL>

会话1:

--创建索引(因为要在 会话2、会话3 中做其它操作,所以表中数据要量要足够大)

10:25:08 SQL> create index ix_test_col1 on t_test(col1);

Index created.

Elapsed: 00:00:59.73

会话2:

--修改指定行的索引字段,此时update语句会hang住,等待索引创建,从会话3 中的锁的情况可以看到 会话2 在等待 会话1

10:25:04 SQL> update t_test set col1=102400 where col2=102400;

1 row updated.

Elapsed: 00:01:02.63

会话3:

--查看此时锁的情况

10:24:29 SQL> select a.*, decode(a.type, \'TM\', b.object_name) table_name

from v$lock a, dba_objects b

where a.id1=b.object_id(+)

and a.sid in(144, 147);

SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK TABLE_NAME

-* --------- ---------- ------- ---------- ------------ ------------ ---------- ------- -----

144 TM 18 0 3 0 1 0 OBJ$

147 TM 5180637 0 0 3 0 0 T_TEST

144 TM 5180637 0 4 0 3 1 T_TEST

144 DL 5180637 0 3 0 3 0

144 DL 5180637 0 3 0 3 0

144 TX 655384 57423 6 0 3 0

6 rows selected.

Elapsed: 00:00:02.12

10:25:52 SQL> /

这里看到普通索引创建 要加TM TX DL 三把锁,更新语句正在等待要加TX锁

SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK TABLE_NAME

147 TM 5180637 0 3 0 4 0 T_TEST

147 TX 393221 56619 6 0 4 0

Elapsed: 00:00:00.77

当索引创建完 了后 更新语句才加到锁.

因此普通索引创建的时候 会阻塞 索引字段上的DML操作! 主要是因为不喜欢别的会话更改索引字段的值,否则导致索引叶节点的键值与表数据不一致.

create index online

会话1:

--删除索引,并加online选项重建

10:26:46 SQL> drop index ix_test_col1;

Index dropped.

Elapsed: 00:00:00.35

10:26:59 SQL> create index ix_test_col1 on t_test(col1) online;

Index created.

Elapsed: 00:02:47.07

会话2:

--修改指定行的索引字段,此时update不会待索引创建,而是很快结束

10:26:50 SQL> update t_test set col1=102400 where col2=102400;

1 row updated.

Elapsed: 00:00:09.21

会话3:

--查看锁的情况

10:26:53 SQL> /

SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK TABLE_NAME

147 TM 5180637 0 3 0 6 0 T_TEST

144 TM 5180637 0 2 0 7 0 T_TEST

144 DL 5180637 0 3 0 8 0

144 DL 5180637 0 3 0 8 0

144 TM 5180671 0 4 0 7 0 144 TX 327692 57125 6 0 8 0

147 TX 655370 57432 6 0 6 0

7 rows selected.

Elapsed: 00:00:02.16

这里看到DML语句也加到了TX锁,而索引也加了3把锁.

.online创建索引时会临时创建一个IOT的表,把后期DML 记录到该表中,索引创建结束后删除IOT表 事实上就是类似于MVCC 回滚段的味道

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值