128 位整数的 MySQL 数据类型

Kam*_*ami 13 mysql datatypes

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

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

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

Joe*_*Joe 11

我不知道存储它的最佳方法是什么——但至少有一个比使用 a 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)
Run Code Online (Sandbox Code Playgroud)

在本例中,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
);
Run Code Online (Sandbox Code Playgroud)

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

以下是查询。

笔记:

X_[HIGH/LOW] 是 X 的最高/最低有效 64 位

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

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
Run Code Online (Sandbox Code Playgroud)

平均响应时间:

平均响应时间

BINARY_InnoDB  0.0119529819489
BINARY_MyISAM  0.0139244818687
DECIMAL_InnoDB 0.017379629612
DECIMAL_MyISAM 0.0179929423332
BIGINT_InnoDB  0.782350552082
BIGINT_MyISAM  1.07809265852
Run Code Online (Sandbox Code Playgroud)


Ben*_*enV 2

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

  • 我认为如果您只想存储数据,这会起作用。 (2认同)