在MySQL中将十六进制值存储为二进制

时间:2009-11-11 04:03:49

标签: mysql binary hex

我在想我是如何在我的数据库中存储密码的:在CHAR(40)字段中适当加盐的SHA1字符串。但是,由于其中的字符数据实际上只是160位数的十六进制表示,我认为将它存储为BINARY(20)可能更好。

CREATE TABLE users (
    password BINARY(20)
    /* snip */
);

INSERT INTO users (password) VALUES (UNHEX(SHA1('mypassword'));

正如我所看到的,这种方法的一个好处是它将该字段的大小减半,但我可以想象也可能存在一些缺点。

你有什么看法?

6 个答案:

答案 0 :(得分:26)

我们在数据库中使用二进制文件来存储大量不同的ID以节省空间,因为我们的大部分数据都包含这些ID。因为它似乎不需要节省空间(因为它只是密码,而不是其他大型项目),我认为没有任何理由在这里使用二进制文件。

我们遇到的最大问题是不断地,令人讨厌的是,在控制台中显示二进制数据(每次键入select *你会听到一百万次哔声),你必须总是选择HEX()或插入UNHEX() ,这是一种痛苦。

最后,如果你混合和匹配(错误地)二进制和HEX / UNHEX并加入这个值,你可以匹配你从未想过的记录。

答案 1 :(得分:7)

这是我的细分:

  1. 如果使用字符串而不是二进制,请使用固定长度字段。由于散列算法都输出固定的长度,你可以节省一些空间。
  2. 由于您只进行相等比较,因此不需要索引。二进制字段没有排序规则类型或字符集。
  3. BINARY列类型没有像BLOB那样奇怪的存储警告。
  4. 每个十六进制字符代表它消耗的8(或7)位中的4位。这意味着二进制存储的效率是原来的两倍。
  5. 最重要的是:除非您在每个字节都很重要的嵌入式系统中工作,否则不要这样做。具有字符表示将允许您更好地调试。此外,每次开发人员正在处理这样的问题时,我都不知道为什么。像这样的每个架构决策都有权衡,而这似乎不会为您的项目增加价值。
  6. 您可以随后使用简单的SQL脚本转换为BINARY。
  7. 简而言之,使用固定长度的文本字段。在当前世界中计算字节没有任何好处,特别是在容易实现变化时。

    希望这会有所帮助。

答案 2 :(得分:2)

将散列密码存储为二进制而非varchar的硬盘空间节省可能无关紧要。您在此表中可能拥有多少用户?乘以BINARY(20)VARCHAR(n)之间的空格差异,我认为您会发现它并不是一笔可观的节省。就个人而言,我更喜欢十六进制表示,因为至少我可以在查询中输入它,如果我在开发期间进行一些临时操作或编写单元测试来验证密码相关操作。如果我碰巧在文本编辑器中加载数据转储等,则Hex比二进制文件更具可读性。我的底线是在开发周期中十六​​进制表示会更方便。

答案 3 :(得分:2)

如果你想在sql中存储二进制文件的简单方法...你可以转换为十六进制。 看看这个页面: http://kekoav.com/blog/36-computers/58-uuids-as-primary-keys-in-mysql.html

转换为十六进制,取下“ - ”并将“0x”放在字符串前面。 Mysql将理解为字节内容。

实施例: INSERT INTO用户SET密码= 0x1e8ef774581c102cbcfef1ab81872213

答案 4 :(得分:2)

这是一个老问题,但我注意到没有人提到数据验证作为BINARY列的优势。具体来说,可以使用非十六进制数字(0-9,a-f)的字符在CHAR(40)列中存储无效值。

您仍然可以将错误的值插入BINARY列(例如,如果您忘记调用UNHEX),但您永远不必考虑从数据库中读取无法正确解析的值。

答案 5 :(得分:0)

为什么重新发明轮子?为什么不使用像表`mysql.user'那样的CHAR(41)?这是一种众所周知的格式,因此任何未来的维护者都不会对您的特殊计划感到头疼?只需注意“就像MySQL密码一样”,让每个人都感到轻松。