我需要将128位无符号整数存储到MySQL中,我想知道什么是存储如此大数字的最佳数据类型。
现在,我正在使用,binary(16)
但这涉及很多转换功能pack(/huge number in hex .../)
。
有没有最好的数据类型来存储128位无符号整数?
我需要将128位无符号整数存储到MySQL中,我想知道什么是存储如此大数字的最佳数据类型。
现在,我正在使用,binary(16)
但这涉及很多转换功能pack(/huge number in hex .../)
。
有没有最好的数据类型来存储128位无符号整数?
Answers:
我不知道最好的存储方式是什么-但是至少有一个比使用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个字节),我希望您能够直接对它进行数学运算,但是我已经从来没有尝试过这么多的数字,看看会发生什么。
我发现自己在问这个问题,在我读过的所有文章中都没有发现任何性能比较。所以这是我的尝试。
我创建了以下表格,其中填充了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
我相信唯一的选择是将其存储在varchar(39)
字段中。