是否通过索引ID字段拆分查询避免ORA-01555:快照太旧错误?

时间:2014-06-26 02:00:26

标签: sql oracle rollbacksegments

我对表单有一些疑问:

select * from MAIN.MY_TABLE 
    where ID in (select ID from OTHER.OTHER_TABLE where type = 'BANANA');

IDMAIN.MYTABLE上编入索引,但未在OTHER.OTHER_TABLE上编入索引

最近,ORA-01555: snapshot too old发生了这些错误。

我的理解是这是由于查询占用撤消空间的时间太长。

这可能是因为它是商业旺季,而且数据库处于高负荷状态。

问题是,如果我将查询拆分为表单的几个查询:

select * from MAIN.MY_TABLE 
    where ID in (select ID from OTHER.OTHER_TABLE where type = 'BANANA') 
        and ID >= 0 and ID <1000;

select * from MAIN.MY_TABLE 
    where ID in (select ID from OTHER.OTHER_TABLE where type = 'BANANA') 
        and ID >= 1000 and ID <2000;

select * from MAIN.MY_TABLE 
    where ID in (select ID from OTHER.OTHER_TABLE where type = 'BANANA') 
        and ID >= 2000 and ID <3000;

一方面,这似乎每个查询比初始查询花费的时间更少。另一方面,这似乎是一个明显的优化,我认为Oracle无论如何都会这样做。

2 个答案:

答案 0 :(得分:1)

为什么不尝试优化查询,因此不需要这么长时间?对于初学者,如果使用IN(SELECT ...)而不是连接,Oracle可能难以构建一个好的查询计划。此查询是否使用更好的查询计划(即JOIN运算符而不是IN运算符)返回相同的结果:

select * from MAIN.MY_TABLE 
inner join
OTHER.OTHER_TABLE 
on MAIN.MY_TABLE.ID = OTHER.OTHER_TABLE.ID
and OTHER.OTHER_TABLE.type = 'BANANA';

唯一的问题是OTHER.OTHER_TABLE列上的ID中是否有重复项。这将导致最终结果集中的重复计数。但是如果可能的话,你应该真的避免使用那种IN (SELECT....)结构。

答案 1 :(得分:1)

此查询假设返回的行数与MY_TABLE中的行数相比?

MY_TABLE.ID上的索引将有助于行数中的行数(从OTHER.OTHER_TABLE中选择不同的ID,其中type ='BANANA')~MID_TABLE中行数的2-5%。

所以我先检查这些数字。我会尝试这样的查询:

select * 
from MAIN.MY_TABLE a,
     (select distinct ID from OTHER.OTHER_TABLE where type = 'BANANA') b
where a.id = b.id;

如果为true,并且使用MY_TABLE上的索引(根据执行计划),我会检查执行的速度(从OTHER.OTHER_TABLE中选择不同的ID,其中type ='BANANA'):

select count(1)
from
(select distinct ID from OTHER.OTHER_TABLE where type = 'BANANA')

P.S。 要在sqlplus中获得真正的执行计划:

set linesize 200
set autotrace traceonly
    select * 
    from MAIN.MY_TABLE a,
         (select distinct ID from OTHER.OTHER_TABLE where type = 'BANANA') b
    where a.id = b.id;