MySQL数据类型为128位整数


12

我需要将128位无符号整数存储到MySQL中,我想知道什么是存储如此大数字的最佳数据类型。

现在,我正在使用,binary(16)但这涉及很多转换功能pack(/huge number in hex .../)

有没有最好的数据类型来存储128位无符号整数?


4
我不禁要注意,这是第二个问题,在这个问题中,您似乎必须对解决方案做一些奇怪的事情才能使用MySql。您是否考虑过更强大的数据库平台?
罗素Steen

我倾向于看看当我们仍在处理8和16位系统时,FORTRAN和其他语言如何支持64位整数。

@Russel Steen,作为更强大的数据库平台,您会要求什么?
卡米

您仍然需要打包和解压缩它,但Postgres具有本机128位类型
Gaius

实际上,Postgres bigserial类型应该做到这一点。
Gaius

Answers:


10

我不知道最好的存储方式是什么-但是至少有一个比使用varchar(39)(或varchar(40)如果需要签名)更好的选择;而是使用decimal(39,0)从mysql文档

定点(精确值)类型

DECIMAL和NUMERIC类型存储精确的数字数据值。当保留精确度很重要时,例如使用货币数据,则使用这些类型。在MySQL中,NUMERIC被实现为DECIMAL,因此以下有关DECIMAL的说明同样适用于NUMERIC。

MySQL 5.1以二进制格式存储DECIMAL值。在MySQL 5.0.3之前,它们存储为字符串。请参见第11.18节“精度数学”。

在DECIMAL列声明中,可以(通常是)指定精度和小数位数;例如:

salary DECIMAL(5,2)

在此示例中,5是精度,2是小数位。精度表示值存储的有效位数,小数位数表示小数点后可以存储的位数。

标准SQL要求DECIMAL(5,2)能够存储任何具有五位数字和两位小数的值,因此可以存储在薪水列中的值的范围是-999.99到999.99。

在标准SQL中,语法DECIMAL(M)等效于DECIMAL(M,0)。类似地,语法DECIMAL等效于DECIMAL(M,0),其中允许实现决定M的值。MySQL支持DECIMAL语法的这两种变体形式。M的默认值为10。

如果小数位数为0,则DECIMAL值不包含小数点或小数部分。

DECIMAL的最大位数为65,但是给定DECIMAL列的实际范围可能受给定列的精度或小数位数的限制。如果为该列分配的值在小数点后的位数比指定刻度允许的位数多,则该值将转换为该刻度。(精确的行为是特定于操作系统的,但是通常效果是将其截断为允许的位数。)

它是打包存储的,因此它比varchar占用更少的空间(如果我对数学没错,则要占用18个字节),我希望您能够直接对它进行数学运算,但是我已经从来没有尝试过这么多的数字,看看会发生什么。


8

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

我创建了以下表格,其中填充了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

平均响应时间:

平均响应时间

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

2

我相信唯一的选择是将其存储在varchar(39)字段中。


2
我认为如果您只想存储数据,这将起作用。
eiefai 2011年

1
@eiefai:那不是他在问什么吗?“我需要存储128位无符号整数”
BenV 2011年

哦,是的,这是个很好的建议,我只是在进行评论以确保他只想存储而不是进行一些计算。
eiefai 2011年

@eiefai:好的,我误会了。您是完全正确的,必须将值强制转换为数字。
BenV 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.