【问题标题】:Storing hexadecimal values as binary in MySQL在 MySQL 中将十六进制值存储为二进制
【发布时间】:2010-12-15 08:06:11
【问题描述】:

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

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

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

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

你有什么意见?

【问题讨论】:

  • 每个密码只会节省几个字节。值得吗?
  • 这就是我想知道的。收益可能微乎其微,但成本是多少?
  • 好吧,似乎大家一致同意,好处微乎其微,没有人建议任何重大成本。如果您进行了更改,将来的备份会与过去的备份兼容吗?是否需要更改任何代码?

标签: mysql binary hex


【解决方案1】:

我们在数据库中为大量不同的 id 使用二进制来节省空间,因为我们的大部分数据都由这些 id 组成。由于您似乎不需要节省空间(因为它只是密码,而不是其他一些大型项目),我看不出有任何理由在这里使用二进制。

我们遇到的最大问题是控制台中不断显示二进制数据(每次键入 select * 都会听到一百万声哔哔声),而且您必须始终执行 select HEX() 或 insert UNHEX() ,这是一种痛苦。

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

【讨论】:

【解决方案2】:

这是我的细分:

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

简而言之,使用固定长度的文本字段。在当前世界中计算字节数没有任何好处,尤其是在很容易实现更改的情况下。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 您可以随时调用 HEX(myBinaryField) 将其查看为十六进制。
    • @nickf:当然可以。只是不太方便。
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

      转换成十六进制,去掉“-”,在字符串前面加上“0x”。 Mysql会理解为字节内容。

      例子:

      INSERT INTO users SET password=0x1e8ef774581c102cbcfef1ab81872213
      

      【讨论】:

        【解决方案6】:

        为什么要重新发明轮子?为什么不像表 `mysql.user' 使用CHAR(41)?这是一种众所周知的格式,所以任何未来的维护者都不会对你的特殊方案摸不着头脑吗?只需注意“就像 MySQL 密码一样”,让每个人都轻松。

        【讨论】:

          猜你喜欢
          • 2011-08-07
          • 2012-05-24
          • 1970-01-01
          • 2016-08-12
          • 2022-01-22
          • 2012-06-26
          • 1970-01-01
          • 1970-01-01
          • 2017-04-20
          相关资源
          最近更新 更多