3

我打算将文件名和其他详细信息存储在一个表中,我打算使用文件名的 sha1 哈希作为 PK。

  • Q1。SHA1 PK 不会是一个顺序增加/减少的数字。那么,数据库维护/search_into 和索引该键是否会消耗更多资源?如果我决定将它作为 40 字符值保存在数据库中。

  • Q2。我在这里读到: https ://stackoverflow.com/a/614483/986818将数据存储为二进制(20)字段。有人可以在这方面给我建议:

  • a) 我是否必须将此列创建为:TYPE=integer、LENGTH=20、
    COLLATION=binary、ATTRIBUTES=binary?
  • b) 如何将 MySQL 或 Perl 中的 sha1 值转换为存储到表中?
  • c) 这 20 个字符的值是否存在重复的危险?

**

- - - - -更新 - - - - - - -

**

要求是在文件名上搜索表。用户提供文件名,我去搜索表,如果文件名不存在,则添加它。因此,要么我在 varchar(100) 文件名字段上编制索引,要么生成一个带有文件名 sha1 的列 - 希望与索引 varchar 字段相比,为 MySql 编制索引会更容易。我也可以使用我的程序中的 sha1 值对 sha1 列进行搜索。说啥?主键或只是索引键:我选择 PK 因为 DBIx 喜欢使用 PK。并且 PK 或 INDEX+UNIQ 对系统来说将是相同数量的开销(所以我认为)

4

5 回答 5

0

这里没有理由使用加密安全哈希。相反,如果您这样做,请使用普通哈希。见这里:https ://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed

哈希不是 40 字符值!这是一个 160 位的数字,您应该以这种方式存储它(作为 20 字符的二进制字段)。编辑:我看到你在评论 2 中提到了这一点。是的,你绝对应该这样做。但是我不能告诉你怎么做,因为我不知道你使用的是什么编程语言。Edit2:我看到它是 perl - 抱歉,我不知道如何在 perl 中转换它,但寻找“pack”函数。

不,不要将其创建为整数类型。最大整数是 128 位,不包含整个内容。尽管您实际上可以将其截断为 128 位而不会造成真正的伤害。

无论如何,最好使用更简单的哈希。你可以冒险并忽略碰撞,但如果你做得好,你有点不得不处理它们。

于 2012-08-19T20:08:24.290 回答
0

如果我决定将它作为 40 字符值保存在数据库中。

由于显而易见的原因,使用字符序列作为键会降低性能。

PK也应该是唯一的。尽管您最终不太可能发生冲突(理论上将其用于创建 PK 的函数似乎不合适。
此外,任何知道您使用的文件名和哈希的人都会知道您的所有数据库 ID。我不确定是否这是不应该考虑的事情。

于 2012-08-19T20:13:15.493 回答
0

Q1:是的,它需要建立一个节点的 B 树,其中不仅包含 1 个整数(4 个字节),还包含一个 CHAR(40)。只要 INDEX 保存在内存中,速度就会大致相同。由于条目大约大 10 倍,因此您需要多 10 倍的内存才能将其保存在内存中。但是:无论如何,您可能都想通过哈希查找。因此,您需要将其作为主键或索引。

Q2:只需创建一个表字段,如 CREATE TABLE test (ID BINARY(40), ...); 稍后您可以使用 INSERT INTO test (ID, ..) VALUES (UNHEX('4D7953514C'), ...);

- 关于:这 20 个字符的值是否存在重复的危险?

机会是 1 in 2^(8*20)。1 in 1,46 * 10^48 ... 或 1 的 14615016373309029182036848327163*10^18。所以这个机会是非常非常v..不可能的。

于 2012-08-19T20:13:33.030 回答
0

我会坚持使用主键的标准自动递增整数。如果文件名的唯一性很重要(听起来确实如此),那么您可以在文件名本身或文件名的某些派生的规范版本上添加 UNIQUE 约束。大多数语言/框架都有某种方法来获取路径的规范版本(相对于绝对、标准化大小写等)。

如果您实施我的建议或追求您的原始计划,那么您应该知道多个字符串可以映射到相同的文件名/路径。两个版本都有不同的哈希值/通过唯一性约束,但实际上都引用同一个文件。这取决于操作系统,对您来说可能是也可能不是问题。只是要记住的事情。

于 2012-08-19T20:18:36.287 回答
0

好的,然后在文件名上使用非常短的散列并接受冲突。为它使用整数类型(那要快得多!!!)。例如,您可以使用 md5(filename) 然后使用前 8 个字符并将它们转换为整数。SQL 可能如下所示:

CREATE TABLES files (
  id INT auto_increment,
  hash INT unsigned,
  filename VARCHAR(100),

  PRIMARY KEY(id),
  INDEX(hash)
);

然后你可以使用:

SELECT id FROM files WHERE hash=<hash> AND filename='<filename>';

然后哈希用于整理大多数其他文件(通常是所有其他文件),然后文件名用于从少数哈希冲突中选择正确的条目。

为了在 perl 中生成整数哈希键,我建议使用 md5() 和 pack()。

于 2012-08-19T20:56:17.590 回答