2013-05-13 83 views
0

多个计算是没有办法,我可以通过避免像 避免了相同的值

regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|TO|.csv|\d+:\d{2}:\d{2}', '') 
一些重复值的倍数计算提高此查询性能的方法是什么? 和

to_date(regexp_replace(regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}', ''), '^(\d{4}-\d+-\d+)_.+$', '\1'), 'YYYY-MM-DD') 

这列被计算3和2的时间,我拼命地跑一些测试,仅通过去除DATE_START列中的查询性能由约20秒改善。我想如果oracle提供了一个更好的方法来保留这些值,并避免多次计算会很好。我也想避免

实际查询:

 
select * 
from (
    select 
     row_number() over (partition by DCRAINTERNALNUMBER, ISSUE_DATE, PERMIT_ID order by to_date(regexp_replace(regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}', ''), '^.+_(\d{4}-\d+-\d+)_$', '\1'), 'YYYY-MM-DD') desc) as row_order, 
     to_date(regexp_replace(regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}', ''), '^(\d{4}-\d+-\d+)_.+$', '\1'), 'YYYY-MM-DD') as date_start, 
     to_date(regexp_replace(regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}', ''), '^.+_(\d{4}-\d+-\d+)_$', '\1'), 'YYYY-MM-DD') as date_end, 
     temp2.* 
    from schema.TABLE_NAME temp2 
) t 

我也试着模仿这样的事情,以避免重复计算,但是由于所有的嵌套的SELECT语句没有提高什么...它使查询与慢约25秒:

 
select * 
from (
    select row_number() over (partition by DCRAINTERNALNUMBER, ISSUE_DATE, PERMIT_ID order by date_end desc) as row_order, 
    temp1.* 
    from (
     select to_date(regexp_replace(date_raw, '^(\d{4}-\d+-\d+)_.+$', '\1'), 'YYYY-MM-DD') as date_start, 
      to_date(regexp_replace(date_raw, '^.+_(\d{4}-\d+-\d+)_$', '\1'), 'YYYY-MM-DD') as date_end, 
     temp2.* 
     from (
     select regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}', '') as date_raw, 
     temp3.* 
     from schema.TABLE_NAME temp3 
    ) temp2 

) temp1 
) t 

+0

你可以尝试CTE- http://docs.oracle.com/cd/B28359_01/server 0.111/b28286/statements_10002.htm#i2161315 – 2013-05-13 10:29:40

回答

2

如果这是很少的输入值的确定性PL/SQL的功能,我想肯定是尝试改变:

select expensive_function(some_value) 
from large_table; 

...到...

select (select expensive_function(some_value) from dual) 
from large_table; 

...如Oracle有一个缓存机制。您可能只是将SQL表达式推入子查询中,如果这样做不起作用(或者即使这样做),我也会将该SQL代码移动到PL/SQL函数中并尝试使用。

哦,如果你在课程11g的我会使用PL/SQL函数缓存直接:http://www.oracle.com/technetwork/issue-archive/2007/07-sep/o57asktom-101814.html

+0

我会首先使用pl/sql,但这不是我正在处理的过程中要做的事......从双语句中选择似乎稍微改进了最后一个查询,但是当我添加一个订单然后查询减慢了很多(比没有减少了约30倍)(这是针对没有从双重选择的查询...对于具有来自双重选择函数的查询只减慢约10倍的查询)。这非常酷,非常感谢! :) – 2013-05-14 06:47:31

+0

回想起来,您可能还想尝试一种非正则表达式方法来查找您需要的日期。使用“Instr(my_source_file,'_', - 49)​​+1”应该通过向后计数找到下划线来安全地找到您的第一年值(可以使用“instr(..., - 1,6)+1”但它可能是一个效率较低的阴影)以及类似的instr来查找结束日期的下划线。正则表达式很方便,但通常要慢得多。 – 2013-05-14 09:13:38

0

不知道,这将提高很多,但你可以用一个CTE:

with cte as (
    select tt.*, to_date(regexp_replace(regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}', ''), '^.+_(\d{4}-\d+-\d+)_$', '\1'), 'YYYY-MM-DD') calc_val 
    from schema.TABLE_NAME tt 
) 
select * 
from (
    select 
     row_number() over (partition by DCRAINTERNALNUMBER, ISSUE_DATE, PERMIT_ID order by calc_val desc) as row_order, 
     calc_val as date_start, 
     calc_val as date_end, 
     temp2.* 
    from cte temp2 
) t 
+0

我试过版本CTE的查询,但在一切都没有改善的时间(工作几乎就像第二个查询)。感谢你的回答! – 2013-05-13 10:56:26

+0

你能举几个你想要的数据的例子吗? – Dave 2013-05-13 12:10:56

+0

来自my_source_file列的值的示例:TABLE_NAME_2011-3-1_11:00:00_AM_TO_2013-4-24_12:00:00_AM.csv – 2013-05-13 12:41:04

1

它不会回答你的具体问题有关减少调用的次数的功能,但你有没有考虑过使用REGEXP_SUBSTR,而不是多次调用REGEXP_REPLACE功能?我认为这样可以减少工作量,并且应该更快。这也应该是不太可能给你一个例外,如果数据不完全匹配(例如,如果文件名应该是.txt代替的.csv)

喜欢的东西...

select * 
from (
    select row_number() over (partition by DCRAINTERNALNUMBER, ISSUE_DATE, PERMIT_ID order by to_date(regexp_substr(my_source_file,'\d{4}-\d{1,2}-\d{1,2}'),'yyyy-mm-dd') desc) as row_order, 
    to_date(regexp_substr(my_source_file,'\d{4}-\d{1,2}-\d{1,2}'),'yyyy-mm-dd') as date_start, 
    to_date(regexp_substr(my_source_file,'\d{4}-\d{1,2}-\d{1,2}',1,2),'yyyy-mm-dd') as date_end, 
    temp2.* 
from schema.TABLE_NAME temp2) t 

如果我已妥善解释您的数据

TABLE_NAME_2011-3-1_11:00:00_AM_TO_2013-4-24_12:00:00_AM.csv 

在此2011-3-1是开始日期,2013-4-24是结束日期。我可以用相同的模式匹配,但采摘一审的开始日期(没有参数是必需的,因为这是默认的)和结束日期的第二个实例(这需要额外得到这些为日期,为1,2 。在SUBSTR中开头(字符1)

希望帮助启动,并挑选二审

+0

regexp_substr在查询上没有取得很大改进,但是当我将它与通过选择顺序将时间缩短了50%...因此,使用推荐的@davidaldridge和regexp_substr(...)的双重选择函数将时间从约60-70秒提高到约12秒。这是很多!感谢您的回答! – 2013-05-14 07:01:37

相关问题