mysql 中整数数组的最小存储?

smallest storage of integer array in mysql?

我有一个 table 的用户条目,对于每个条目,我都有一个(2 字节)整数数组来存储(15-25,偶尔甚至更多)。数组元素将同时写入和读取,永远不需要更新或单独访问它们。他们的顺序很重要。将其视为数组对象是有道理的。

我有数百万个这样的用户条目,我想用尽可能少的磁盘存储这些条目 space。然而,我正在为 MySQL 缺少 Array 数据类型而苦苦挣扎。

我一直在考虑以下选项。

MySQL有更好的方法吗?我知道 MySQL 有一个有效的 varchar 类型,所以理想情况下我将我的 2 字节整数存储为 varchar 中的 2 字节字符(或类似的方法 blob), 但我不确定该怎么做。这可能吗?应该怎么做?

您可以将它们存储为单独的 SMALLINT NULL 列。

在 MyISAM 中,这对每个值使用 2 个字节的数据 + 1 位空指示符。

在 InnoDB 中,空指示符被编码到列的 字段起始偏移量 ,因此它们不会占用任何额外的 space,并且空值实际上不是存储在行数据中。如果行足够小以至于所有偏移量都是 1 字节,那么这将对每个现有值(1 字节偏移量,2 字节数据)使用 3 个字节,对每个不存在的值使用 1 个字节。

这两种方法都比使用带有特殊值的 INT 来表示它不存在要好,因为每个值都需要 4 个字节的数据。

NULL in MySQL (Performance & Storage)

评论里给出了最佳答案,所以我会把它和一些可用的代码重新发布在这里,以供进一步参考。

MySQL 有一个 varbinary 类型非常适合这个:你可以简单地使用 PHP 的 pack/unpack 函数来转换它们来回二进制形式,并使用varbinary将该二进制形式存储在数据库中。转换的示例代码如下。

function pack24bit($n) { //input: 24-bit integer, output: binary string of length 3 bytes
    $b3 = $n%256;
    $b2 = $n/256;
    $b1 = $b2/256;
    $b2 = $b2%256;
    return pack('CCC',$b1,$b2,$b3);
}

function unpack24bit($packed) { //input: binary string of 3 bytes long, output: 24-bit int
    $arr = unpack('C3b',$packed);
    return 256*(256*$arr['b1']+$arr['b2'])+$arr['b3'];
}