Oracle:优化大输入regex_substr解析以使用POSITION参数而不是OCCURRENCE参数

时间:2015-06-10 20:42:41

标签: oracle plsql oracle11g plsqldeveloper

我需要帮助优化我的代码或提供可提供时间效率结果的替代方案。

我使用Oracle 11GR2 11.2.0.4.0

我正在编写一个包含一个充满HTML源代码的clob并在html标记之间获取文本的包。我按预期工作的代码,但根据clob中内容的大小,它可能需要永远执行。

我理解使用出现参数的 regexp_substr 可能是瓶颈,我相信如果我可以将其迁移到使用位置参数然后它会运行得更快。

我总共有四个函数,其中两个函数用于管理从函数数组列表函数返回的行。

每个列表函数( return_rows_list return_rows_list2 )将以不同方式解析HTML。例如, return_rows_list 将使用子查询因子, return_rows_list2 将使用PL / SQL和变量来存储 regexp_substr 的结果。我创建了 return_rows_list2 函数,以了解哪种方法最快。这两种功能对于任何实际使用场景都是慢的,彼此之间的距离是10秒。

我需要以某种方式替换使用出现参数的 regexp_substr ,而不是使用 regexp_instr 位置参数>

下面的包需要一些源HTML代码才能正常工作。我建议使用任何网页并将源代码输入变量。我使用select语句来输入clob,因为实际上源将大于32767个字符,并且PL / SQL不会接受大于该字符串的字符串文字。

包来源:

CREATE OR REPLACE package pipe_html_contents as
type rows_t is record( rec varchar2(32767));

type t_rows_list is table of rows_t index by binary_integer;
type t_rows_tab is table of rows_t;

function return_rows_list return t_rows_list;

function return_rows return t_rows_tab PIPELINED;

function return_rows2 return t_rows_tab PIPELINED;

function return_rows_list2 return t_rows_list;

end pipe_html_contents;
/

套餐正文:

CREATE OR REPLACE package body pipe_html_contents as

function return_rows return t_rows_tab PIPELINED IS
l_returnValue t_rows_list;
begin
l_returnValue:=return_rows_list;
for i in 1 .. l_returnValue.count loop
    pipe row (l_returnValue(i));
  end loop;

  return;
end;

function return_rows2 return t_rows_tab PIPELINED IS
l_returnValue t_rows_list;
begin
l_returnValue:=return_rows_list2;
for i in 1 .. l_returnValue.count loop
    pipe row (l_returnValue(i));
  end loop;

  return;
end;

function return_rows_list return t_rows_list IS
l_returnValue t_rows_list;
p_clob clob:='';
c_temp clob;
    l_count                        pls_integer := 0;       
begin
   for l_rec in ( with src    as (select (select SOURCE from temp)) as html from dual) --Source HTML Code goes here. Replace the select SOURCE from temp with the source HTML code from your website of choice.
                    ,fields as (select html
                                      ,regexp_replace(regexp_replace(html
                                                                    ,'<[^<>]+>'
                                                                    ,'▌')
                                                     ,'▌+'
                                                     ,'▌') data
                                      ,length(regexp_replace(regexp_replace(regexp_replace(html
                                                                                          ,'<[^<>]+>'
                                                                                          ,'▌')
                                                                            ,'▌+'
                                                                            ,'▌') 
                                                            ,'[^▌]+'
                                                            ,''))-2 num_fields
                                from src)
                select trim(regexp_substr(data,'[^▌]+',1,level)) field
                from   fields
                connect by level <= num_fields)
                LOOP

                   if length(l_rec.field) > 2 then
                     l_count:=l_count +1;
                     l_returnValue(l_count).rec:=l_rec.field;
                   end if;

                END LOOP;

    return l_returnValue;
end;


function return_rows_list2 return t_rows_list IS
l_returnValue t_rows_list;
p_clob clob;
c_temp clob;
l_Matches pls_integer;
v_match clob:=null;
    l_count                        pls_integer := 0;       
begin

select SOURCE into p_clob from temp; --Source HTML Code goes here. Replace the select SOURCE into p_clob from temp with the source HTML code from your website of choice.

c_temp:=regexp_replace(regexp_replace(p_clob , '<[^<>]+>' ,'▌'),'^[▌]+' ,'▌');

l_Matches:=length(regexp_replace(regexp_replace(regexp_replace(p_clob, '<[^<>]+>','▌'),'^[▌]+','▌'),'[^▌]+',''))-2;

for i in 1 .. l_Matches
LOOP
    v_match:=trim(regexp_substr(c_temp,'[^▌]+',length(regexp_replace(regexp_replace(regexp_replace(c_temp, '<[^<>]+>','▌'),'^[▌]+','▌'),'[^▌]+',''))+1,i));

    if length(v_match) > 2 then
        l_count:= l_count+1;
        l_returnValue(l_count).rec:=v_match;
    end if;
END LOOP;                                         
    return l_returnValue;
exception 
  when others then
     dbms_output.put_line(sqlerrm);
end;
end pipe_html_contents;
/

用法示例:

select * from table(pipe_html_contents.return_rows); -- for sub-query factoring

select * from table(pipe_html_contents.return_rows2); -- for Make shift sub-query facoring

0 个答案:

没有答案