2013-04-17 29 views

Trả lời

4

Đối với SQL, tôi đã thử nghiệm điều này với các kịch bản sau đây:

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 
) 
); 

và thấy rằng hiệu suất của translateregexp_replace là hầu như luôn luôn giống nhau, nhưng nó có thể được rằng chi phí của các hoạt động khác là áp đảo các chi phí của các chức năng tôi đang cố gắng để kiểm tra.

Tiếp theo, tôi đã thử một phiên bản 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; 
/

Đây là phiên bản translate chỉ mất dưới 10 giây, trong khi phiên bản regexp_replace khoảng 0,2 giây - khoảng 2 bậc độ lớn nhanh hơn

(!)

Dựa trên kết quả này, tôi sẽ sử dụng cụm từ thông dụng thường xuyên hơn trong mã quan trọng hiệu suất của tôi - cả SQL và PL/SQL.

+3

Tôi nghĩ bạn đang nhảy đến một kết luận một chút vội vã ở đây :) Nếu bạn nghĩ về nó, chỉ tối ưu hóa bộ nhớ cache mới có thể giải thích mức độ chênh lệch này trong thời gian chạy. Trong một ví dụ thế giới thực, bạn sẽ không chuyển đổi cùng một chuỗi hơn và hơn tôi nghi ngờ. –

+2

Tuy nhiên, thật thú vị khi thấy rằng trong một số trường hợp 'regexp' ** nhanh hơn ** so với' dịch' :) –

+0

Vào ngày 10g, tôi thấy REGEXP_ đáng tin cậy một hoặc hai đơn hàng có cường độ chậm hơn so với các điểm tương tự không phải REGEXP của chúng (khi làm đủ thứ để đo sự khác biệt). Tuy nhiên, 10g là bản phát hành đầu tiên với các chức năng regex tích hợp và tôi đã dự kiến ​​Oracle sẽ có một số điều chỉnh quan trọng cho 11g. – APC

10

Tôi nghĩ bạn đang chạy vào tối ưu hóa đơn giản. Biểu thức regexp quá tốn kém để tính toán kết quả được lưu trữ với hy vọng rằng nó sẽ được sử dụng lại trong tương lai. Nếu bạn thực sự sử dụng các chuỗi riêng biệt để chuyển đổi, bạn sẽ thấy rằng bản dịch khiêm tốn tự nhiên nhanh hơn vì nó là chức năng chuyên môn của nó.

Dưới đây là ví dụ của tôi, chạy trên 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 

trên 11.2.0.3.0:

regex  :+000000000 00:00:00.617290000 
translate :+000000000 00:00:00.138205000 

Kết luận: Nói chung tôi nghi ngờ translate sẽ giành chiến thắng.

Các vấn đề liên quan