26

假设我想使用哈希作为 ID 而不是数字。BINARY将它们存储为非二进制文件会带来性能优势吗?

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

2 回答 2

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 秒。虽然我们可以测量速度的相对差异,但速度的绝对差异确实微不足道。

所以我要重申:

  • 衡量,不要猜测或假设。你有根据的猜测在很多时候都是错误的。在您进行每次更改之前和之后进行测量,这样您就知道它有多大帮助。
  • 将您的时间和精力投入到获得最大收益的地方。
  • 不要为小事出汗。当然,一个微小的差异加上足够的迭代次数,但考虑到这些迭代次数,具有更大绝对收益的性能改进仍然是可取的。
于 2009-02-02T19:01:01.603 回答
6

手册

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)后台创建列,因此好处是按该列排序将花费更少的时间,并且如果该列被索引,则可能更少的时间来查找相应的行。

于 2009-02-02T18:40:36.823 回答