1

IPアドレスを整数に変換する関数をOracleで作成しました。遅いようでした。同じことをより速く行うための 2 番目の関数を作成しました。残念ながら遅くなりましたが、その理由はわかりません。

オリジナル機能;

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;

これも機能しますが、実行速度が大幅に (約 2 倍) 遅くなるようです。累乗関数または regexp_substr のいずれかが豚であると想定します。しかし、私は、より多くの知識を持つ誰かが、どれを、および/またはその理由を指摘することを望んでいました.

4

2 に答える 2

0

これが私の小さな知識です。Oracle11gには、階層型PL/SQLプロファイラがあります。これにより、pl/sqlがどこで時間を費やしているかがわかります。

于 2013-02-19T18:04:08.797 に答える
0

regexp_substr通常の よりも遅くなりsubstrpower. しかし、ほとんどの時間は中になりregexp_substrます。

しかし、なぜ「遅い」と言うのか不思議です。私はあなたがたくさんの電話を意味していると思いますか?私がそれらをテストしたとき、ルーチンはかなりきびきびしているので。

また、このタイプの関数は、ネイティブ コンパイルの恩恵を大きく受けます (DBA はこれを機能させるために何もする必要がないため、11g では簡単に実行できます)。

最後に、これがわずかに高速であることに気付くかもしれません (特にネイティブ コンパイルの場合)。

create or replace function get_ip_integer3(ip_in in varchar2) 
return integer 
as
  result integer := 0;
begin
  result := result + 16777216 * substr(ip_in, 1, instr(ip_in, '.') - 1);
  result := result +
            65536 * substr(ip_in, instr(ip_in, '.') + 1,
                           instr(ip_in, '.', 1, 2) - instr(ip_in, '.') - 1);
  result := result +
            256 * substr(ip_in, instr(ip_in, '.', 1, 2) + 1,
                         instr(ip_in, '.', 1, 3) - instr(ip_in, '.', 1, 2) - 1);
  result := result + substr(ip_in, instr(ip_in, '.', 1, 3) + 1);

  return result;
end get_ip_integer3;
于 2013-02-19T18:06:18.027 に答える