【问题标题】:Using a hash as a primary key?使用哈希作为主键?
【发布时间】:2012-07-03 13:39:06
【问题描述】:

我需要存储多台计算机的服务列表。我想我会创建一个表来保存所有可能的表的列表,一个用于所有可能的计算机的表,然后是一个将服务链接到计算机的表。

我正在考虑保持完整服务列表的唯一性,我可以使用可执行文件的哈希作为服务的主键,但我不确定这是否有任何缺点(请注意,哈希仅用于识别。不用于任何类型的安全目的)。我在考虑而不是使用二进制字段作为主/外键,而是将值存储为 base 64 编码的 sha512,并使用nvarchar(88)。类似的东西:

CREATE TABLE Services
(
  ServiceHash nvarchar(88) NOT NULL,
  ServiceName nvarchar(256) NOT NULL,
  ServiceDescription nvarchar(256),
  PRIMARY KEY (ServiceHash)
)

此解决方案是否存在任何固有问题? (我将使用 SQL 2008 数据库并通常通过 C#.Net 访问它)。

【问题讨论】:

  • 哈希不保证是唯一的。只需使用 GUID
  • Nvarchar(88) - 这可能是一个非常宽(和可变长度)的密钥;如果您将其用作该表上的集群键(默认情况下是 PK),您将不会对该表的性能非常满意!
  • @marc_s 变得更好。由于 theat 是散列中的 base64 编码数字,因此 varchar 的 N 部分从未根据定义使用,因此您将存储加倍完全没用。好点,我忽略了这一点。

标签: c# database sql-server-2008


【解决方案1】:

问题是散列在定义上不是唯一的。您不太可能发生碰撞,但有可能。结果,你不能只使用hash,这意味着整个hash id是死胡同。

使用普通的 ID 字段,在 ServiceName 上使用带有索引的唯一约束。

【讨论】:

  • 硬碰撞真的很少见。
【解决方案2】:

从性能的角度来看,使用非增量主键会导致聚集索引很快产生碎片。

我建议:

  1. 使用 INTBIGINT 代理 PK,自动递增。
  2. 使用sequential GUID 作为PK。索引不如INT 快​​,但增量,因此碎片时间低。

然后,您可以在其他列上使用非聚集索引,包括存储哈希的列。作为VARCHAR,您还可以对其进行全文索引,然后在查找特定哈希时进行精确匹配。

但是,如果可能,请改用数字哈希并在其上创建非聚集索引。

当然,请考虑下面提到的@TomTom

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 2011-12-03
    • 2013-02-24
    • 2014-10-16
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    相关资源
    最近更新 更多