【问题标题】:MySQL binary against non-binary for hash IDsMySQL 二进制与哈希 ID 的非二进制
【发布时间】:2010-10-04 23:49:35
【问题描述】:

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

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

【问题讨论】:

  • 您能否更具体地说明您在寻找什么“优势”?您是否正在尝试针对空间、性能、易用性或独特价值范围进行优化?
  • 我主要对性能优势感兴趣,因为空间几乎是空闲的,而且 128 位值是使用 BIGINT 作为主键的值范围的两倍。

标签: mysql string binary


【解决方案1】:

是的。哈希摘要通常存储为十六进制数字的 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')));

回复。你的 cmets 你更关心性能而不是空间效率:

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

所以我再重申一遍:

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

【讨论】:

  • 我已经想到了。尽管 2^128 已经足够了(BIGINT 只有 2^64,这已经足够了),但它会为我节省一半的空间。
  • 我已按照您的要求更新了我的问题。如果您再看一下,我会很好。
  • 我认为二进制会更快,因为没有像普通比较那样对大小写字母进行额外比较,因此“'foo'='FOO'”为真,但“BINARY 'foo '='FOO"” 假。
  • 感谢您的回复。我已经忘记了。感谢您对基准测试的提示。我也没有考虑到这一点。我想我会建立两个测试用例并自己测量。虽然我认为我肯定会使用 16 字节长的 BINARY 变体,甚至将其缩短为 8 字节。
  • 一个 MD5 哈希总是 16 字节。如果您将存储空间缩短到 8 个字节,您将存储一个截断的哈希值。如果没关系,请继续。
【解决方案2】:

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

【讨论】:

  • 感谢您的回答。你不会碰巧知道这方面的一些数据吗?
猜你喜欢
  • 2019-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
  • 1970-01-01
  • 2015-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多