Oracle 大规模 delete,update 操作 注意事项
一. 说明
如果对大表进行大规模的delete 和update,那么可以注意一下如下说明:
(1) 查看执行计划,如果说删除的记录很多,走索引的成本会比全表扫描更大,因为更新数据时还需要做一些约束校验和创建index entry。而且对于多CPU 情况,全表扫描还可以使用并行的特性。
Oracle Parallel Execution(并行执行)
http://blog.csdn.net/tianlesoftware/archive/2010/09/01/5854583.aspx
(2)如果表上有索引,B-Tree 索引可以unusable索引,函数索引则disable 索引,等操作结束之后在rebuild索引。
(3)如果是大规模的delete,那么可能还需要注意一下高水位的问题,在允许的情况下,可以用alter table move 来降低高水位,同时注意rebuild 索引。
Oracle 高水位(HWM: High Water Mark) 说明
http://blog.csdn.net/tianlesoftware/archive/2009/10/21/4707900.aspx
如果是OLTP的生产环境,对于禁用索引和高水位处理的操作要慎重。
二. 相关测试
--查看表中记录数
SYS@dave2(db2)> select count(*) from dave;
COUNT(*)
----------
3080115
--查看索引信息
SYS@dave2(db2)> select index_name from dba_indexes where table_name='DAVE';
INDEX_NAME
------------------------------
IDX _PRCODE
IDX _STATE
IDX _INSERT
SYS_C005469
--创建一个备份表,下次使用
SYS@dave2(db2)> create table dave1 as select /*+parallel(t,3)*/ * from dave t;
Table created.
--查看执行计划
SYS@dave2(db2)> explain plan for delete from dave where time_insert<to_date('2011-5-1','yyyy-mm-dd');
SYS@dave2(db2)> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2615685836
---------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost (%cpu)| time |
---------------------------------------------------------------------------
| 0 | delete statement | | 1369k| 26m| 7916 (3)| 00:01:35 |
| 1 | delete | dave | | | | |
|* 2 | table access full| dave | 1369k| 26m| 7916 (3)| 00:01:35 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------
2 - filter("time_insert"<to_date('2011-05-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss'))
15 rows selected.
--查看走执行计划的大规模update 操作
SYS@dave2(db2)> explain plan for update dave d set getcard_code=10 where state=2;
Explained.
SYS@dave2(db2)> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3706120077
-------------------------------------------------------------------------------
| id | operation | name | rows | bytes | cost (%cpu)| time |
-------------------------------------------------------------------------------
| 0 | update statement | | 96254 | 469k| 2533 (1)| 00:00:31 |
| 1 | update | dave | | | | |
|* 2 | index range scan| idx_state | 96254 | 469k| 194 (2)| 00:00:03 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------
2 - access("STATE"=2)
14 rows selected.
--禁用索引
SYS@dave2(db2)> alter index idx_state unusable;
Index altered.
SYS@dave2(db2)> select status from dba_indexes where index_name='IDX_STATE';
STATUS
--------
UNUSABLE
--如果是对进行delete 操作,那么相关的索引要全部禁用才起作用。
--更新数据
SYS@dave2(db2)> update dave d set state=10 where state=2;
101837 rows updated.
SYS@dave2(db2)> commit;
Commit complete.
--rebuild 索引
SYS@dave2(db2)> alter index idx_state rebuild;
Index altered.
Oracle alter index rebuild 说明
http://blog.csdn.net/tianlesoftware/archive/2011/06/12/6538928.aspx
-- 查看高水位
SYS@dave2(db2)> select num_rows,blocks,empty_blocks from dba_tables where table_name='DAVE';
NUM_ROWS BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
3080115 35350 0
num_rows 的值只有做过统计信息收集之后才有,如果该值与count(*) 差距太大,就说明需要重新进行收集了。
empty_blocks 参数只有使用analyze 收集统计信息才有,使用dbms_stats 收集不到这个参数的信息。 如果empty_blocks 较多,就说明有高水位了。
SYS@dave2(db2)> analyze table dave compute statistics;
Table analyzed.
SYS@dave2(db2)> select num_rows,blocks,empty_blocks from dba_tables where table_name='DAVE';
NUM_ROWS BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
3080115 35350 4585
有关统计信息更多内容参考:
Oracle Statistic 统计信息 小结
http://blog.csdn.net/tianlesoftware/archive/2009/10/14/4668723.aspx
--处理高水位
SYS@dave2(db2)> alter table dave move;
Table altered.
--move 会使所有索引失效,需要重新rebuild
SYS@dave2(db2)> select index_name,status from dba_indexes where table_name='DAVE';
INDEX_NAME STATUS
------------------------------ --------
IDX_PRCODE UNUSABLE
IDX_STATE UNUSABLE
IDX_INSERT UNUSABLE
SYS_C005469 UNUSABLE
--rebuild 索引
SYS@dave2(db2)> alter index IDX_PRCODE rebuild;
Index altered.
SYS@dave2(db2)> alter index IDX_STATE rebuild;
Index altered.
SYS@dave2(db2)> alter index idx_insert rebuild;
Index altered.
SYS@dave2(db2)> alter index SYS_C005469 rebuild;
Index altered.
SYS@dave2(db2)> select index_name,status from dba_indexes where table_name='DAVE';
INDEX_NAME STATUS
------------------------------ --------
IDX_PRCODE VALID
IDX_STATE VALID
IDX_INSERT VALID
SYS_C005469 VALID
-- 使用analyze 分析表
SYS@dave2(db2)> analyze table dave compute statistics;
Table analyzed.
SYS@dave2(db2)> select num_rows,blocks,empty_blocks from dba_tables where table_name='DAVE';
NUM_ROWS BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
3080115 35487 4448
因为我这里没有进行大量的delete 操作,效果很有限。
-------------------------------------------------------------------------------------------------------
Blog: http://blog.csdn.net/tianlesoftware
Email: dvd.dba@gmail.com
DBA1 群:62697716(满); DBA2 群:62697977(满) DBA3 群:62697850(满)
DBA 超级群:63306533(满); DBA4 群: 83829929 DBA5群: 142216823
DBA6 群:158654907 聊天 群:40132017 聊天2群:69087192
--加群需要在备注说明Oracle表空间和数据文件的关系,否则拒绝申请