1

我在 Oracle 中编写了一个函数来将 IP 地址转换为整数。似乎很慢。我写了第二个函数来更快地做同样的事情。不幸的是,它最终变慢了,我不知道为什么。

原创功能;

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 是一头猪。但我希望有更多知识的人可以指出哪个,和/或为什么。

4

2 回答 2

0

这是我的小知识:在 oracle 11g 中,您拥有分层 PL/SQL 分析器。这将向您显示您的 pl/sql 花费时间的地方。

于 2013-02-19T18:04:08.797 回答
0

regexp_substr会比普通的慢substr,而且会有一点开销power。最多的时间会在regexp_substr虽然。

我很好奇你为什么说它们“慢”。我想你的意思是打了很多电话?因为当我测试它们时,这些例程非常活泼。

此外,这种类型的函数将从本机编译中受益匪浅(这在 11g 中很容易做到,因为 dba 不需要做任何事情来让它工作)。

最后,您可能会发现这稍微快一些(尤其是使用本机编译)。

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 回答