我在Oracle中編寫了一個函數來將IP地址轉換爲整數。它看起來很慢。我寫了第二個函數來更快地完成同樣的事情。不幸的是,結果變慢了,我不知道爲什麼。這兩個oracle函數爲什麼表現不同?
原函數;
FUNCTION GET_IP_INTEGER
(
IP_IN IN VARCHAR2
) RETURN NUMBER AS
DOT_COUNTER INTEGER;
CURRENT_DOT INTEGER;
LAST_DOT INTEGER := 1;
CURRENT_INTEGER INTEGER := 0;
OUTPUT_INTEGER INTEGER := 0;
BEGIN
FOR DOT_COUNTER IN 1..3
LOOP
CURRENT_DOT := INSTR(IP_IN,'.',LAST_DOT);
CURRENT_INTEGER := TO_NUMBER(SUBSTR(IP_IN,LAST_DOT,CURRENT_DOT - LAST_DOT));
LAST_DOT := CURRENT_DOT + 1;
CASE DOT_COUNTER
WHEN 1 THEN CURRENT_INTEGER := CURRENT_INTEGER * 16777216;
WHEN 2 THEN CURRENT_INTEGER := CURRENT_INTEGER * 65536;
WHEN 3 THEN CURRENT_INTEGER := CURRENT_INTEGER * 256;
END CASE;
OUTPUT_INTEGER := OUTPUT_INTEGER + CURRENT_INTEGER;
CURRENT_INTEGER := 0;
END LOOP;
CURRENT_INTEGER := TO_NUMBER(SUBSTR(IP_IN,LAST_DOT));
OUTPUT_INTEGER := OUTPUT_INTEGER + CURRENT_INTEGER;
RETURN OUTPUT_INTEGER;
END GET_IP_INTEGER;
它把所有東西都分開,運作良好。但我認爲我可以做得更好,所以我寫了這個;
FUNCTION GET_IP_INTEGER1
(
IP_IN IN VARCHAR2
) RETURN NUMBER AS
OCTET_COUNTER INTEGER;
CURRENT_INTEGER INTEGER := 0;
OUTPUT_INTEGER INTEGER := 0;
BEGIN
FOR OCTET_COUNTER IN 1..4
LOOP
CURRENT_INTEGER := TO_NUMBER(REGEXP_SUBSTR(IP_IN,'\w+',1,OCTET_COUNTER));
CURRENT_INTEGER := POWER(2,24 - ((OCTET_COUNTER-1)*8)) * CURRENT_INTEGER;
OUTPUT_INTEGER := OUTPUT_INTEGER + CURRENT_INTEGER;
END LOOP;
RETURN OUTPUT_INTEGER;
END GET_IP_INTEGER1;
這也行得通,但似乎運行速度較慢(約兩倍長)。我會假設冪函數或regexp_substr是一隻豬。但我希望有更多知識的人可能會指出哪些和/或爲什麼。
我張貼另一個問題(http://stackoverflow.com/questions/14964562/how-can-you-force-an-function-in-a-where-clause-to-execute-once-in -oracle)我實際上使用這個函數,執行時間從4.33秒變爲11秒。 – 2013-02-19 18:20:32