针对哈希ID的非二进制的MySQL二进制文件

时间:2009-02-02 18:24:00

标签: mysql string binary

假设我想使用哈希作为ID而不是数字。将它们作为BINARY存储在非二进制文件中是否具有性能优势?

CREATE TABLE `test`.`foobar` (
  `id` CHAR(32) BINARY CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
  PRIMARY KEY (`id`)
)
CHARACTER SET ascii;

2 个答案:

答案 0 :(得分:29)

是。通常,哈希摘要存储为十六进制数字的ASCII表示,例如“哈希”一词的MD5为:

0800fc577294c34e0b28ad2839435945

这是一个32个字符的ASCII字符串。

但是MD5确实产生了128位的二进制哈希值。此应该只需要将16个字节存储为二进制值而不是十六进制数字。因此,您可以通过使用二进制字符串来获得一些空间效率。

CREATE TABLE test.foobar (
  id BINARY(16) NOT NULL PRIMARY KEY
);

INSERT INTO test.foobar (id) VALUES (UNHEX(MD5('hash')));

重新。你的意见是你更关注绩效而不是空间效率:

我不知道BINARY数据类型比CHAR更快的原因。

如果您有效地使用缓存缓冲区,那么一半大可以提高性能。也就是说,如果字符串的大小是以十六进制存储相同值所需的CHAR的一半,则给定数量的高速缓冲存储器可以存储两倍于BINARY数据的行。同样,该列上索引的高速缓存也可以存储两倍。

结果是一个更有效的缓存,因为随机查询更有可能命中缓存的数据或索引,而不需要磁盘访问。缓存效率对于大多数数据库应用程序很重要,因为通常瓶颈是磁盘I / O.如果你可以使用高速缓冲存储器来降低磁盘I / O的频率,那么降压比一种数据类型或另一种数据类型之间的选择要大得多。

至于存储在BINARY中的哈希字符串与BIGINT之间的区别,我会选择BIGINT。缓存效率会更高,而且在64位处理器上整数运算和比较应该非常快。

我没有测量来支持上述声明。选择一种数据类型而不是另一种数据类型的净收益很大程度上取决于数据库和应用程序中的数据模式和查询类型。要获得最精确的答案,您必须尝试两种解决方案并衡量差异。


重新。假设二进制字符串比较比默认的不区分大小写的字符串比较更快,我尝试了以下测试:

mysql> SELECT BENCHMARK(100000000, 'foo' = 'FOO');
1 row in set (5.13 sec)

mysql> SELECT BENCHMARK(100000000, 'foo' = BINARY 'FOO');
1 row in set (4.23 sec)

因此二进制字符串比较比不区分大小写的字符串比较快17.5%。但请注意,在评估此表达式1亿次后,总差异仍然小于1秒。虽然我们可以测量速度的相对差异,但速度的绝对差异实际上是微不足道的。

所以我会重申:

  • 测量,不要猜测或假设。你的有根据的猜测在很多时候都是错的。在每次更改之前和之后进行测量,以便了解它有多大帮助。
  • 将你的时间和精力投入到获得最大收益的地方。
  • 不要为小东西出汗。当然,微小的差异会增加足够的迭代次数,但是考虑到这些迭代次数,性能提升和绝对优势仍然更可取。

答案 1 :(得分:6)

来自the manual

The BINARY and VARBINARY types are similar to CHAR and VARCHAR, except
that they contain binary strings rather than non-binary strings. That is,
they contain byte strings rather than character strings. This means that
they have no character set, and sorting and comparison are based on the
numeric values of the bytes in the values. 

因为CHAR(32)BINARY导致在引擎盖下创建BINARY(32)列,所以好处是它按照该列排序所需的时间更少,如果列是,则查找相应行的时间可能更短索引。