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

Sql 按索引ID字段拆分查询是否可以避免ORA-01555:快照太旧错误?,sql,oracle,rollbacksegments,Sql,Oracle,Rollbacksegments,我对表格有一些疑问: select * from MAIN.MY_TABLE where ID in (select ID from OTHER.OTHER_TABLE where type = 'BANANA'); select * from MAIN.MY_TABLE where ID in (select ID from OTHER.OTHER_TABLE where type = 'BANANA') and ID >= 0 and ID &l

我对表格有一些疑问:

select * from MAIN.MY_TABLE 
    where ID in (select ID from OTHER.OTHER_TABLE where type = 'BANANA');
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;
其中ID在MAIN.MYTABLE上索引,但在OTHER.OTHER_表上未索引

最近,ORA-01555出现了错误:快照太旧

我的理解是,这是因为查询占用的撤消空间太长

这可能是因为现在正是业务旺季,数据库负载很重

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

select * from MAIN.MY_TABLE 
    where ID in (select ID from OTHER.OTHER_TABLE where type = 'BANANA');
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;

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

为什么不尝试优化查询,这样就不会花那么长时间?首先,如果在SELECT中使用,Oracle可能很难构建好的查询计划。。。而不是加入。此查询是否使用更好的查询计划返回相同的结果,即使用联接运算符而不是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';

唯一的问题是ID列上的OTHER.OTHER_表中是否存在重复项。这将导致最终结果集中的重复计数。但你真的应该避免这种选择。。。。结构(如果可能)。

与MY_表中的行数相比,此查询应该返回多少行

如果MY_TABLE.ID中的行数中的行数与OTHER.OTHER_TABLE中的行数不同,则MY_TABLE.ID上的索引将有所帮助,其中type='BANANA'~MY_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_表上的索引,我将检查执行type='BANANA'的select distinct ID与OTHER.OTHER_表的速度:

select count(1)
from
(select distinct ID from OTHER.OTHER_TABLE where type = 'BANANA')
附言。 要在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;

将第二个sql放入以最小和最大id为参数的过程中也会更快。是否使用ASSM自动段空间管理?undo_retention参数的值是多少?两个表中的行数是多少?其他_表中的类型是否已索引?你希望有多少行?撤消表空间有多少空间?在数据库修改过程中还会发生什么?@ik_zelf-我只是数据库的最终用户,无法访问大量有关数据库的信息。DBA很难找到,一个5000人左右的组织有三个DBA。如果你的问题解决了一个业务问题,我希望通过给你合适的资源就能解决。现在:不,分裂没有帮助。如果没有所需的信息,就没有有效的答案。一般来说,Oracle用这样一个简单的查询建立一个好的计划不会有困难-在这种情况下,子查询untesting工作得很好。例如,我构建了一个简单的示例,两个版本的计划几乎相同。请注意,这个SQLFIDLE不能很好地工作。它无法正确解析解释计划,您需要在本地运行它才能查看真正的计划。可能MY_表上有大约100万条记录,而其他_表上有10万条记录。重要的是,通过选择与其他不同的ID返回多少条记录。其他_表中,type='BANANA'。表OTHER_表本身的大小仅影响此子查询。是-子查询返回的10m。