我正在使用 MySql 来存储这种格式的基本表:
id int(11) //Auto-Incrementing ID
data varchar(5120) //Random input data, compressed by a program, not mysql.
-----------------------
Row size ø 916 B
这有点麻烦,因为现在我每个月大约有 5,000 条记录,我想优化它而不是最终平均为 1mb/1000 条记录。
我最初以这种方式设置它是因为我希望能够捕获更大的集合,但它们很少见,正如您在此图表中看到的那样:
count n*128 bytes
+-------+----------
1 28
1 26
1 24
2 22
8 21
4 20
13 19
12 18
16 17
27 16
43 15
58 14
69 13
114 12
184 11
262 10
399 9
588 8
807 7
1224 6
1245 5
546 4
73 3
9 2
6 1
1 0
我在这里主要关心的是我浪费了多少空间来容纳该图表的尾端,以及当我最终得到更大的异常值时会发生什么?当大约 80% 的数据非常适合 varchar 1024 块时,我将不得不再次增加行大小,这是我现在使用的大小的 1/5。
那么我应该如何首先构建这个东西呢?
由于它已经构建,让我们看看你有什么。有一种有趣的方法可以为当前存在的数据规划列定义。如果表名是 mydata,请尝试运行此查询:
从 mydata PROCEDURE ANALYZE () 中选择数据;
这不会显示您的任何数据。这将检查列
data
本身,根据前 256 个不同的值计算统计信息(默认情况下,您可以指定不同的值计数)并推荐表应具有的正确列类型。只要表是 MyISAM,就不必太担心行的大小,因为默认的行格式是 DYNAMIC。如果表是 InnoDB(我当然希望不是),请确保数据不是 PRIMARY KEY 的一部分。您的聚集索引将像在您的后院倾倒未稀释的 MiracleGro 一样增长。
您可能需要将数据列分成 128 个块并运行 MD5(32 个字符输出)或 SHA1(40 个字符输出)并连接这些 MD5 或 SHA1 输出并存储它们。这将节省 75% 的存储空间。尝试编写分手代码,玩得开心。这只是我脑海中的一个漫无边际的建议。
您可能还想考虑使用 Sphinx 索引。
对于 MyISAM,如果您从不更新或删除记录,则 blob 的 N 字节记录将在 .MYD 文件中占用 N+8 字节。
MyISAM PK 将在 .MYI 文件中找到;它将非常小——大约 11 字节/行,加上一些开销,四舍五入为 1KB 块。
如果您使用的是 InnoDB,布局会相当复杂。有 16KB 的数据块永远不会很满,有 blob 范围(即使是 VARCHAR),它在 767 字节后开始(可能更快,取决于版本),等等。范围以 1MB 的块分配。计划平均每行 2N 字节。
InnoDB PK是和数据一起存储的,所以上面完全包含了。而且,作为 AUTO_INCREMENT,您的块往往会相对满。注意:块大小为 16KB,每个块至少允许 20 个。
不要用自己的分块玩游戏;它会减慢速度,使您的代码复杂化等。磁盘很便宜。(是的,玩这样的游戏很有趣。)
看起来你的一半记录不会超过 767 的截止值。
旁白:如果 blob 是压缩数据,您应该真正使用 BLOB,而不是 VARCHAR。VARCHAR 假定 CHARACTER SET 属性,如果您切换到 utf8,这真的会让您感到头疼。如果必须使用 VAR-xx,请使用 VARBINARY。