代码之家  ›  专栏  ›  技术社区  ›  OhioDude

如何在mySQL中存储IP

  •  24
  • OhioDude  · 技术社区  · 17 年前

    我们将使用perl和python脚本访问数据库,以进一步将数据规范化到其他几个表中,供顶级演讲者、感兴趣的流量等使用。

    我相信社区中有一些人做了一些与我们正在做的事情类似的事情,我很想听听他们的经验,以及哪条路线最好,IP地址是1个大整数还是4个小整数。

    -我们关心的一个问题是空间,这个数据库将是巨大的,每天有500000000条记录。因此,我们正在努力权衡空间问题和性能问题。

    编辑2 有些对话涉及到我们将要存储的数据量……这不是我的问题。问题是哪种存储IP地址的方式更可取,为什么。正如我在评论中所说,我们为一家财富50强的大公司工作。我们的日志文件包含用户的使用数据。这些数据反过来将在安全上下文中用于驱动某些度量和驱动若干安全工具。

    5 回复  |  直到 15 年前
        1
  •  25
  •   Nisse Engström sting_roc    9 年前

    我建议查看您将运行的查询类型,以决定采用哪种格式。

    只有在需要拔出或比较各个八位字节时,才需要考虑将它们分成单独的字段。

    INET_ATON() INET_NTOA()

    性能与空间

    存储:

    UNSIGNED INT 它只使用4字节的存储空间。

    要存储单个八位字节,只需使用 UNSIGNED TINYINT SMALLINTS ,这将占用每个存储器的1字节。

    这两种方法都将使用类似的存储,可能会稍微多一些用于单独的字段,以节省一些开销。

    更多信息:

    使用单个字段将产生更好的性能,这是一个单一的比较,而不是4。您提到,您将只对整个IP地址运行查询,因此不需要将八位字节分开。使用 INET_* MySQL的函数将在文本和整数表示之间进行一次转换,以进行比较。

        2
  •  14
  •   John Topley    17 年前

    A. BIGINT 8 MySQL .

    储存 IPv4 UNSINGED INT 够了,我想这是你应该用的。

    我无法想象会发生什么情况 4 八位组将获得比单个八位组更高的性能 INT ,后者更方便。

    还请注意,如果您要发出如下查询:

    SELECT  *
    FROM    ips
    WHERE   ? BETWEEN start_ip AND end_ip
    

    哪里 start_ip end_ip

    这些查询用于确定给定的 IP 在子网范围内(通常禁止)。

    为了使这些查询有效,您应该将整个范围存储为 LineString SPATIAL

    SELECT  *
    FROM    ips
    WHERE   MBRContains(?, ip_range)
    

    有关如何操作的更多详细信息,请参阅我的博客中的这篇文章:

        3
  •  4
  •   Greg Hewgill    17 年前

    native data type 为此。

    更严重的是,我会陷入“一个32位整数”阵营。IP地址只有在将四个八位字节考虑在一起时才有意义,因此没有理由将八位字节存储在数据库中的单独列中。您会使用三个(或更多)不同的字段存储电话号码吗?

        4
  •  3
  •   Rich Bradshaw    17 年前

    对我来说,使用单独的字段听起来并不特别明智——就像将zipcode拆分为多个部分或电话号码一样。

        5
  •  1
  •   user105033    17 年前

    (PERL)

    sub ip2dec {
        my @octs = split /\./,shift;
        return ($octs[0] << 24) + ($octs[1] << 16) + ($octs[2] << 8) + $octs[3];
    }
    
    sub dec2ip {
        my $number = shift;
        my $first_oct = $number >> 24;
        my $reverse_1_ = $number - ($first_oct << 24);
        my $secon_oct = $reverse_1_ >> 16;
        my $reverse_2_ = $reverse_1_ - ($secon_oct << 16);
        my $third_oct = $reverse_2_ >> 8;
        my $fourt_oct = $reverse_2_ - ($third_oct << 8);
        return "$first_oct.$secon_oct.$third_oct.$fourt_oct";
    }
    
        6
  •  1
  •   hanshenrik    6 年前

    对于ipv4和ipv6的兼容性,请使用VARBINARY(16),ipv4将始终是二进制的(4),ipv6将始终是二进制的(16),因此VARBINARY(16)似乎是支持这两者的最有效方式。要将其从普通可读格式转换为二进制格式,请使用INET6_-ATON('127.0.0.1'),反之,请使用INET6_-NTOA(二进制)

        7
  •  0
  •   Roger    7 年前

    老线程,但为了读者的利益,考虑使用IP2LUN。它将ip转换为整数。

    基本上,当存储到DB时,您将使用ip2long进行转换,然后在从DB检索时使用long2ip进行转换。DB中的字段类型将为INT,因此与将ip存储为字符串相比,可以节省空间并获得更好的性能。

    推荐文章