3个文本字段的唯一索引

时间:2010-07-12 15:12:18

标签: mysql database-design

我需要在表格中存储来自不同来源的评论。 字段:

  • 'produtcId'char(14)
  • 'user'varchar(128)
  • '来源'varchar(128)
  • 'content'text`

用例:

  1. 查找产品的所有评论
  2. 插入或更新评论
  3. 我在案例2中遇到了麻烦,因为我需要查看审核是否已经存在(使用相同的produtcId,用户和来源进行审核)。

    问题:通过produtcId + user + Source创建主键或唯一索引是否合适?

1 个答案:

答案 0 :(得分:3)

这是自然键变坏的情况,varchar(128)对我书中的PK来说很大。它迫使你在评论表中有一个很大的胖(非常宽)的PK或索引。我这样做:

Products
ProductID     int autoincrement PK
ProductNumber char(14)
ProductName...
...

Users
UserID        int autoincrement PK
UserName      varchar(128)
...

ProductSources
ProductSourcID  int autoincrement PK
ProductSource   varchar(128)
...

Reviews
ReviewID      int autoincrement PK
ProductID     int FK
UserID        int FK
ProductSourcID  int FK
ReviewContent text
....

如果您真的只需要对每个产品+用户+来源进行1次审核,那么您可以在ProductID + UserID + ProductSourcID上创建唯一索引。

您可以考虑制作PK:ProductID + UserID + ProductSourcID。但是,如果您需要FK到另一个表中的评论,那么您需要拖动ProductID + UserID + ProductSourcID。我更喜欢FK到ReviewID。

在任何情况下int + int + int自动增量ProductID + UserID + ProductSourcID都比char(14)+ varchar(128)+ varchar(128)版本更好,无论是在磁盘存储和缓存内存使用方面。数据库使用和存储固定宽度的int + int + int索引值要比char(14)+ varchar(128)+ varchar(128)版本容易得多。

此外,通过使用自动增量PK,用户可以更改其用户名(结婚/离婚)并且不会中断所有FK。它将强制所有的ProductSource值被标准化,而不是自由文本,无法加入。

编辑基于OP的评论:

  

这将大大复杂化   插入,我不需要任何   用户或来源的其他信息。   那么使用这个字段的哈希呢   作为主键?

我不确定ID如何使插入复杂化。但是,如果你不能/不愿意改变其他表的PK,那么散列是最好的方法,但我不会把它变成PK。永远不要将哈希值设为PK,可能会发生冲突,从而阻止合法数据的插入。使用自动生成INT作为PK并添加哈希列。你应该这样做。在评论中创建一个名为“ReviewHash”的新列并为其添加索引,如果您预期会发生多次冲突(多个不同的行具有相同的哈希值),您可以将productid,user和source列包括为“覆盖列” 。另外,请WHERE执行此操作:

FROM Reviews
 ....
WHERE 
    YourHashFunction(CONCAT(given_productid,'||',given_user,'||',given_source))=Review.Hash
    AND Review.productid=given_productid 
    AND Review.user=given_user 
    AND Review.source=given_source`  

这将允许在Review.Hash列上使用索引,并且还检查productid,user和source,如果存在哈希冲突,它将消除任何无效数据。

如果您执行以下查询:

WHERE 
    YourHashFunction(CONCAT(given_productid,'||',given_user,'||',given_source))
        =YourHashFunction(CONCAT(Review.productid,'||',Review.user,'||',Review.source))

然后无法使用索引,并且查询必须将YourHashFunction应用于表中的每一行。此外,如果您不使用productid,user和source的检查,您将获得结果,其中哈希值相同但实际值不同。

相关问题