Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql Oracle中regexp_replace与translate的性能?_Sql_Regex_Performance_Oracle_Plsql - Fatal编程技术网

Sql Oracle中regexp_replace与translate的性能?

Sql Oracle中regexp_replace与translate的性能?,sql,regex,performance,oracle,plsql,Sql,Regex,Performance,Oracle,Plsql,对于简单的事情,在CPU密集度较低的前提下使用translate函数更好还是使用regexp\u replace更好 这个问题来自于对于SQL,我使用以下脚本对此进行了测试: set timing on select sum(length(x)) from ( select translate('(<FIO>)', '()[]', '----') x from ( select * from dual connect by level <= 2

对于简单的事情,在CPU密集度较低的前提下使用
translate
函数更好还是使用
regexp\u replace
更好


这个问题来自于

对于SQL,我使用以下脚本对此进行了测试:

set timing on

select sum(length(x)) from (
  select translate('(<FIO>)', '()[]', '----') x
  from (
    select *
    from dual
    connect by level <= 2000000
  )
);

select sum(length(x)) from (
  select regexp_replace('[(<FIO>)]', '[\(\)\[]|\]', '-', 1, 0) x
  from (
    select *
    from dual
    connect by level <= 2000000
  )
);
这里的
translate
版本只需不到10秒,而
regexp\u replace
版本大约需要0.2秒——大约快2个数量级(!)


基于这个结果,我将在性能关键型代码(SQL和PL/SQL)中更频繁地使用正则表达式。

我认为您正在进行简单的优化。regexp表达式的计算成本非常高,因此会缓存结果,希望将来再次使用它。如果您实际使用不同的字符串进行转换,您将看到适度转换自然会更快,因为它是它的专用函数

下面是我在
11.1.0.7.0
上运行的示例:

SQL> DECLARE
  2     TYPE t IS TABLE OF VARCHAR2(4000);
  3     l       t;
  4     l_level NUMBER := 1000;
  5     l_time  TIMESTAMP;
  6     l_char  VARCHAR2(4000);
  7  BEGIN
  8     -- init
  9     EXECUTE IMMEDIATE 'ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL=2';
 10     SELECT dbms_random.STRING('p', 2000)
 11       BULK COLLECT
 12       INTO l FROM dual
 13     CONNECT BY LEVEL <= l_level;
 14     -- regex
 15     l_time := systimestamp;
 16     FOR i IN 1 .. l.count LOOP
 17        l_char := regexp_replace(l(i), '[]()[]', '-', 1, 0);
 18     END LOOP;
 19     dbms_output.put_line('regex     :' || (systimestamp - l_time));
 20     -- tranlate
 21     l_time := systimestamp;
 22     FOR i IN 1 .. l.count LOOP
 23        l_char := translate(l(i), '()[]', '----');
 24     END LOOP;
 25     dbms_output.put_line('translate :' || (systimestamp - l_time));
 26  END;
 27  /

regex     :+000000000 00:00:00.979305000
translate :+000000000 00:00:00.238773000

PL/SQL procedure successfully completed

结论:总的来说,我怀疑
translate
会赢。

我认为您在这里有点仓促地得出了一个结论:)如果您仔细想想,只有缓存优化才能解释运行时的这种巨大差异。在现实世界的例子中,我怀疑你不会反复转换同一个字符串。不过,有趣的是,在某些情况下,
regexp
translate
:)在10g上,我发现regexp_uu确实比它们的非regexp类似物慢一到两个数量级(当做了足够多的事情来衡量差异时)。然而,10g是第一个具有内置正则表达式函数的版本,我本以为Oracle会对11g进行一些重要的调整。
SQL> DECLARE
  2     TYPE t IS TABLE OF VARCHAR2(4000);
  3     l       t;
  4     l_level NUMBER := 1000;
  5     l_time  TIMESTAMP;
  6     l_char  VARCHAR2(4000);
  7  BEGIN
  8     -- init
  9     EXECUTE IMMEDIATE 'ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL=2';
 10     SELECT dbms_random.STRING('p', 2000)
 11       BULK COLLECT
 12       INTO l FROM dual
 13     CONNECT BY LEVEL <= l_level;
 14     -- regex
 15     l_time := systimestamp;
 16     FOR i IN 1 .. l.count LOOP
 17        l_char := regexp_replace(l(i), '[]()[]', '-', 1, 0);
 18     END LOOP;
 19     dbms_output.put_line('regex     :' || (systimestamp - l_time));
 20     -- tranlate
 21     l_time := systimestamp;
 22     FOR i IN 1 .. l.count LOOP
 23        l_char := translate(l(i), '()[]', '----');
 24     END LOOP;
 25     dbms_output.put_line('translate :' || (systimestamp - l_time));
 26  END;
 27  /

regex     :+000000000 00:00:00.979305000
translate :+000000000 00:00:00.238773000

PL/SQL procedure successfully completed
regex     :+000000000 00:00:00.617290000
translate :+000000000 00:00:00.138205000