我有一个包含多列的表格。 "理由"是非索引列之一,可能具有重复值。在我的表中总共有二十万条记录。我想根据特定原因删除行,例如" MY REASON",而有大约15K记录" MY REASON"。
当我使用如下所示的标准删除查询时,需要花费太多时间(大约3或4个小时)。
delete from my_table where reason='MY REASON';
commit;
如何加快速度?
这是相同的执行计划:
Plan hash value: 2164670663
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 6190 | 175K| 1019 (0)| 10:30:49 |
| 1 | DELETE | MY_TABLE | | | | |
|* 2 | TABLE ACCESS FULL| MY_TABLE | 6190 | 175K| 1019 (0)| 10:30:49 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("REASON"='MY REASON')
使用主键删除10row的统计信息,id:
SQL> set timing on;
SQL> set autotrace on explain statistics;
SQL> delete from my_table where id between 194404 and 194414;
11 rows deleted.
Elapsed: 00:00:19.53
Execution Plan
----------------------------------------------------------
Plan hash value: 2403087528
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 29 | 1 (0)| 00:00:38 |
| 1 | DELETE | MY_TABLE | | | | |
|* 2 | INDEX RANGE SCAN| PK_MY_TABLE | 1 | 29 | 1 (0)| 00:00:38 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("id">=194404 AND "id"<=194414)
Statistics
----------------------------------------------------------
94 recursive calls
66 db block gets
602170 consistent gets
0 physical reads
8844 redo size
528 bytes sent via SQL*Net to client
372 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
7 sorts (memory)
0 sorts (disk)
11 rows processed
SQL>
*在儿童桌上添加指数后固定的问题*** 以下是跟踪详细信息:
AFTER ADDING INDEX TO CHILD TABLE
---------------------------------
SQL> set timing on;
SQL> set autotrace on explain statistics;
SQL> delete from MY_TABLE where id between 194241 and 194361;
121 rows deleted.
Elapsed: 00:00:01.37
Execution Plan
----------------------------------------------------------
Plan hash value: 2403087528
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 29 | 1 (0)| 00:00:38 |
| 1 | DELETE | MY_TABLE | | | | |
|* 2 | INDEX RANGE SCAN| PK_MY_TABLE | 1 | 29 | 1 (0)| 00:00:38 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID">=194241 AND "ID"<=194361)
Statistics
----------------------------------------------------------
3 recursive calls
760 db block gets
7 consistent gets
9 physical reads
83968 redo size
527 bytes sent via SQL*Net to client
372 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
5 sorts (memory)
0 sorts (disk)
121 rows processed
答案 0 :(得分:2)
检查外键约束中列的索引。不仅在您的my_table
中,而且在您的所有数据库中。每个外键应在同一列列上具有相应的索引。
创建缺失的索引(具有明确的临时名称,因此您可以在以后轻松删除它们)。
然后再次尝试运行delete
。
答案 1 :(得分:1)
如果删除需要花费很多时间,你可以尝试这样的事情:
1)
CREATE TABLE BACK_MY_TABLE AS SELECT * FROM MY_TABLE
where reason not in ('MY REASON');
2)DROP TABLE MY_TABLE
3)ALTER TABLE BACK_MY_TABLE RENAME TO MY_TABLE
在我看来,有很多索引在路上重建/你在某处使用位图索引。
此外,由于这是Oracle,因此您可以设置允许某些用户(例如,可能是运行这些删除作业的清理用户)的使用者组仅获得X%的可用资源。通过 DEFAULT ,每个进程都会尝试获取所有资源的100%。这会导致争用,并可能极大地影响您的表现。