translate
对于简单的事情,在 CPU 密集度较低的前提下使用该功能更好还是可行regexp_replace
的方法?
问问题
12569 次
2 回答
12
我认为您遇到了简单的优化。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
上11.2.0.3.0
:
regex :+000000000 00:00:00.617290000
translate :+000000000 00:00:00.138205000
结论:总的来说,我怀疑translate
会赢。
于 2013-04-17T11:07:54.680 回答
3
对于 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
几乎regexp_replace
总是相同的,但可能是其他操作的成本超过了我尝试测试的功能的成本。
接下来,我尝试了一个 PL/SQL 版本:
set timing on
declare
x varchar2(100);
begin
for i in 1..2500000 loop
x := translate('(<FIO>)', '()[]', '----');
end loop;
end;
/
declare
x varchar2(100);
begin
for i in 1..2500000 loop
x := regexp_replace('[(<FIO>)]', '[\(\)\[]|\]', '-', 1, 0);
end loop;
end;
/
这里的translate
版本只需要不到 10 秒,而regexp_replace
版本大约需要 0.2 秒——快了大约 2 个数量级(!)
基于这个结果,我将在我的性能关键代码中更频繁地使用正则表达式——SQL 和 PL/SQL。
于 2013-04-17T11:01:52.747 回答