改进DELETE查询Oracle

时间:2015-04-28 15:49:20

标签: oracle plsql

我有一个查询从表中删除一些记录,但需要花费太多时间。 该表在存储过程中使用它来匹配另一个表。

每次执行SP时,表都会被截断,并根据收到的参数填充2或3百万条记录。

该表没有任何FK或约束

删除我正在使用的记录的查询是:

DELETE FROM TABLE1
WHERE (fecha,hora_ini,origen,destino,tipo,valor,rowsm1) IN (
    SELECT fecha_t,hora_t,origen_t,destino_t,tipo,valor,id_t
    FROM TABLE2)

我尝试减少执行查询的时间,该查询基于查询的相同列

创建索引
CREATE INDEX smb1 ON table1 (fecha,hora_ini,origen,destino,tipo,valor,rowsm1);

查询需要更多时间才能执行。

如何提高此“DELETE”查询的效果。

更新

EXPLAIN PLAN OUTPUT

DELETE  TABLE1 

TABLE ACCESS TABLE1

TABLE ACCESS FULL TABLE1  

TABLE ACCESS FULL TABLE2

TABLE ACCESS FULL TABLE2

2 个答案:

答案 0 :(得分:0)

您创建的索引看起来像一个非常大的索引:

CREATE INDEX smb1 
    ON table1 (fecha,hora_ini,origen,destino,tipo,valor,rowsm1);

当然,这取决于数据量,但通常我宁愿寻找一两个selective columns - 如果可能的话。

不要忘记,索引数据也必须被读取,如果它无法帮助加快查询速度,您甚至会失去性能。

如果表非常小,这可能会发生,因为数据库逐块读取数据(我认为它大约是8K)。可以一步读取一个小表 - 这里不需要使用索引。

或者,如果选择了更多或更少的所有记录。在这种情况下,无论如何都必须阅读表格。

如果要加快查询速度,则应在table2上创建相同的索引(具有良好的选择性)。这样EXPLAIN PLAN看起来有点像这样:

DELETE   STATEMENT                  
DELETE      
NESTED   LOOPS SEMI
INDEX    FULL  SCAN
INDEX    RANGE SCAN

答案 1 :(得分:-1)

您可以关闭日志记录并删除行

这是一个例子,你可以用2种方式做到,

1。)将表格物理地转换为Nologging

2.。)在删除语句中使用Nologging提示。

1。)第一种方法

testemp和testemp2都是相同数据的表,而testemp需要一分钟,testemp2只需1秒

SQL> delete from testemp;

14336 rows deleted.

Elapsed: 00:01:04.12
SQL>
SQL>
SQL> alter table testemp2 nologging;

Table altered.

Elapsed: 00:00:02.86
SQL>
SQL> delete from testemp2;

14336 rows deleted.

Elapsed: 00:00:01.26
SQL>

只有当我们使用“Alter”命令物理更改表时,才需要将表重新记录到日志中,如果您使用的是不需要的提示,请参阅下面的示例

2.)第二种方法

SQL> set timing on;
SQL> delete  from testemp2;

14336 rows deleted.

Elapsed: 00:00:01.51

Deleting data after reinserting same data into table now with nologging;



SQL> delete /*+NOLOGGING*/ from testemp2;

14336 rows deleted.
Elapsed: 00:00:00.28

SQL> select logging from user_Tables where table_name='TESTEMP2';

LOG
---
YES