Sql Oracle中regexp_replace与translate的性能?
对于简单的事情,在CPU密集度较低的前提下使用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
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