如何在MySQL的单个列中存储128位数字?

时间:2010-12-14 22:06:23

标签: mysql types ipv6

我正在更改一些表以将IP地址存储为数字而不是字符串。这对于IPv4来说很简单,其中32位地址可以适合整数列。但是,IPv6地址是128位。

MySQL documentation仅显示最多64位的数字类型(“bigint”)。

我应该坚持使用char / varchar进行IPv6吗? (理想情况下,我想对IPv4和IPv6使用相同的列,所以我不想这样做。)

有没有比使用两个bigint列更好的东西?每当使用地址时,我宁愿不必将值分解为上限和下限/。

我正在使用MariaDB 5.1 - 如果在更高版本的MySQL中有更好的解决方案,那么很高兴知道,虽然没有立即帮助。

[编辑] 请注意,我建议最佳方式执行此操作 - 很明显有多种方法可以做到这一点(包括现有的)字符串表示),但哪个(在性能方面)最好? (即如果有人已经完成了分析,这样可以省去我的工作,或者如果我遗漏了一些明显的东西,那么知道这一点也很棒。)

3 个答案:

答案 0 :(得分:42)

我发现自己在问这个问题,从我读过的所有帖子中都没有找到任何性能比较。所以这是我的尝试。

我创建了以下表格,填充了来自100个随机网络的2,000,000个随机IP地址。

CREATE TABLE ipv6_address_binary (
    id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
    addr BINARY(16) NOT NULL UNIQUE
);

CREATE TABLE ipv6_address_twobigints (
    id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
    haddr BIGINT UNSIGNED NOT NULL,
    laddr BIGINT UNSIGNED NOT NULL,
    UNIQUE uidx (haddr, laddr)
);

CREATE TABLE ipv6_address_decimal (
    id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
    addr DECIMAL(39,0) NOT NULL UNIQUE
);

然后我选择每个网络的所有IP地址并记录响应时间。 twobigints表上的平均响应时间约为1秒,而二进制表上的平均响应时间约为百分之一秒。

以下是查询。

  

注意:

     

X_ [HIGH / LOW]是X

的最高/最低有效64位      

当NETMASK_LOW为0时,省略AND条件,因为它总是产生true。不会对性能产生太大影响。

SELECT COUNT(*) FROM ipv6_address_twobigints
WHERE haddr & NETMASK_HIGH = NETWORK_HIGH
AND laddr & NETMASK_LOW = NETWORK_LOW

SELECT COUNT(*) FROM ipv6_address_binary
WHERE addr >= NETWORK
AND addr <= BROADCAST

SELECT COUNT(*) FROM ipv6_address_decimal
WHERE addr >= NETWORK
AND addr <= BROADCAST

平均响应时间:

图表:

http://i.stack.imgur.com/5NJvQ.jpg

BINARY_InnoDB  0.0119529819489
BINARY_MyISAM  0.0139244818687
DECIMAL_InnoDB 0.017379629612
DECIMAL_MyISAM 0.0179929423332
BIGINT_InnoDB  0.782350552082
BIGINT_MyISAM  1.07809265852

答案 1 :(得分:4)

我总是使用一个字符串或两个64位整数。前者是我想记录的情况,后者是我需要计算特定地址是否包含在某个网络中,或者两个网络是否重叠的情况。

将其存储为整数时,唯一的选择是将其拆分为两个64位数。由于这使得比较更加繁琐,除非您需要数值计算,否则我不会这样做,以查看IP是否属于某个网络。

我不太关心将IPv6地址存储在字符串中的性能 - 这取决于您为数据执行的查找次数。通常,很少,或者只有非常少的数据。是的,存储和查找的效率低于数字,但它并不比存储电子邮件地址,人名或用户名更痛苦。

为什么你不能在字符串字段中混合使用IPv4和IPv6?检索它们时很容易区分。它们的可能值范围不重叠。

简而言之:使用数字来检查重叠,在别处使用字符串。与易用性相比,字符串的低效率无关紧要。

答案 2 :(得分:1)

引用:“你考虑过二元(64)”

Storing very large integers in MySQL