2014-02-18 78 views
1

我正在处理大量日期操作的查询(Oracle 11g)。使用行生成器,我正在检查另一个表中每个记录的日期范围内的每个日期。通过另一个查询,我知道我的行生成器需要生成8500个日期,并且这个数量每年将增加365天。另外,我正在研究的表格大约有18000条记录,而且这张表格预计每年会增加几千条记录。如何避免使用行生成器的昂贵的笛卡尔积

将行生成器连接到另一个表以获取每个记录的日期范围时,会出现问题。 SQLTuning Advisor说,有一个昂贵的笛卡尔产品,这是有道理的,因为查询当前可以产生高达8500 x 18000条记录。下面是其精简形式的查询,没有所有的日期逻辑等:

with n as (
    select level n 
    from dual 
    connect by level <= 8500 
) 
select t.id, t.origdate + n origdate  
from (
    select id, origdate, closeddate 
    from my_table 
) t 
join n on origdate + n - 1 <= closeddate -- here's the problem join 
order by t.id, t.origdate; 

有没有加入这两个表没有笛卡尔乘积的替代方法?

我需要计算每个记录的运行时间,禁止周末和联邦节假日,以便我可以对经过的时间进行排序。此外,表的分页是在服务器端完成的,所以我们不能只加载到表中并对客户端进行排序。

现在系统中记录的最大年龄为3656天,平均值为560,因此它不像8500 x 18000那么差。但它仍然不好。

我刚刚辞职加入了一个字段来存储opendays,计算一次并存储经过的时间,并创建一个计划任务以每晚更新所有打开的记录。

+0

你能解释一下为什么你需要生成这么多记录? 8500 x 18000 = 15.300.000行,它必须很慢。 – krokodilko

+0

@kordirko,看看我上面的编辑。 – earachefl

回答

0

我认为,如果你稍微改写连接条件,你会得到更好的性能:

with n as (
    select level n 
    from dual 
    connect by level <= 8500 
) 
select t.id, t.origdate + n origdate  
from (
    select id, origdate, closeddate 
    from my_table 
) t 
join n on Closeddate - Origdate + 1 <= n --you could even create a function-based index 
order by t.id, t.origdate; 
+0

这确实有一点帮助,谢谢,但没有足够的地方。 – earachefl