使用Ruby中的散列将唯一索引添加到MySQL文本字段字符串

时间:2018-05-02 16:44:06

标签: mysql ruby-on-rails hash unique

我有一个Rails应用程序,其模型(表)有1,500,000条记录,文本字段大小介于50到8000个字符之间。

我需要确保文本字段是唯一的。由于我不能在文本字段上使用MySQL唯一索引,我的解决方案是将我的文本字段转换为哈希(使用Digest :: SHA256.hexdigest)并将此哈希保存到名为“body_hash”的varchar字段中。然后在该字段上添加唯一索引。

问题:

  • 我想知道Rails中是否有内置的解决方案吗? (而不是我重新发明轮子 - 到目前为止我找不到任何东西。)
  • 这里使用的另一个哈希算法比Digest :: SHA256.hexdigest更好吗?

2 个答案:

答案 0 :(得分:1)

Rails解决方案是一个before_save钩子。您也可以使用数据库触发器来执行此操作,但这样做会更加混乱和脆弱。

SHA256在这里可能没问题,因为它是基于SHA2的。发生碰撞的可能性应该很小。

使用一致长度哈希而不是唯一索引的文本实际上是一个好主意,因为MySQL的索引对于更长的字符串变得更大。索引引擎处理短十六进制字符串要容易得多,并且仍然提供所需的唯一性约束。

MySQL的独特约束实际上也提供了一种排序机制,这是痛苦的根源,但如果你不关心订购散列解决方案是一个很好的选择。

答案 1 :(得分:1)

您可能需要考虑在数据库本身中生成此校验和/摘要。这样可以更快地回填现有数据的值而不是Ruby中的处理。

结合MySQL的CREATE_DIGEST填充body_digest列:

CREATE_DIGEST('SHA512', 'The quick brown fox');

https://dev.mysql.com/doc/refman/8.0/en/enterprise-encryption-functions.html#function_create-digest

设置此校验和值的BEFORE INSERT / BEFORE UPDATE触发器:

https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html

值得一提的是,在ActiveRecord模型上有一个用于声明数据库触发器的Ruby库: https://github.com/jenseng/hair_trigger