如果我想使用哈希作为ID而不是数字,将它们存储为 BINARY
与非二进制相比会有性能优势吗?
CREATE TABLE `test`.`foobar` (
`id` CHAR(32) BINARY CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
PRIMARY KEY (`id`)
)
CHARACTER SET ascii;
如果我想使用哈希作为ID而不是数字,将它们存储为 BINARY
与非二进制相比会有性能优势吗?
CREATE TABLE `test`.`foobar` (
`id` CHAR(32) BINARY CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
PRIMARY KEY (`id`)
)
CHARACTER SET ascii;
是的。通常哈希摘要以十六进制数字的ASCII表示形式存储,例如单词“hash”的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')));
关于您更关心性能而非空间效率的评论: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%。但请注意,评估此表达式100百万次后,总差异仍不到1秒钟。尽管我们可以测量速度的相对差异,但速度的绝对差异实际上非常微不足道。
所以,我会重申:
'foo'='FOO'
与 'foo'=BINARY 'FOO'
进行基准测试是不公平的。前者必须比较三个字符,而后者在第一个不匹配后可能会停止。当然,这完全是毫秒级别的问题,但仍然值得注意 :) - Michael Krelin - hacker来自手册:
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)
列,因此它的好处是在按该列排序时需要更少的时间,并且如果对该列进行索引,则可能需要更少的时间来查找相应的行。