当前位置:  开发笔记 > 数据库 > 正文

推荐用于标记或标记的SQL数据库设计

如何解决《推荐用于标记或标记的SQL数据库设计》经验,为你挑选了5个好方法。

我听说过几种实现标记的方法; 使用TagID和ItemID之间的映射表(对我有意义,但它是否可以缩放?),向ItemID添加固定数量的可能TagID列(似乎是一个坏主意),将标记保留在逗号分隔的文本列中(声音疯了,但可以工作).我甚至听过有人推荐稀疏矩阵,但那么标签名称如何优雅地增长?

我错过了标签的最佳做法吗?



1> Yaakov Ellis..:

三个表(一个用于存储所有项目,一个用于所有标记,一个用于两者之间的关系),正确编制索引,外键设置在适当的数据库上运行,应该可以正常工作并正确缩放.

Table: Item
Columns: ItemID, Title, Content

Table: Tag
Columns: TagID, Title

Table: ItemTag
Columns: ItemID, TagID


这被称为"Toxi"解决方案,您可以在此处找到有关它的更多信息:http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html
这里没有显示的一件事是Tag表中的分类"标签"或类别.这通常需要具有类别和子类别但需要标记灵活性的站点.例如,配方站点,汽车零件站点,商业目录等.这些类型的数据通常不适合只有一个类别,因此标记是答案,但您需要使用嵌套集模型或邻接列表模型之类的东西在你的标签表中.
@ftvs:链接再次破碎,新链接是http://howto.philippkeller.com/2005/04/24/Tags-Database-schemas/
我使用HK1可以使用以上结构+表:TagGroup列:TagGropuId,标题表:标记列:TagID,Title,TagGroupId

2> Scheintod..:

通常我会同意Yaakov Ellis,但在这个特例中还有另一个可行的解决方案:

使用两个表:

Table: Item
Columns: ItemID, Title, Content
Indexes: ItemID

Table: Tag
Columns: ItemID, Title
Indexes: ItemId, Title

这有一些主要优点:

首先,它使开发变得更加简单:在用于插入和更新的三表解决方案中,item您必须查找Tag表以查看是否已有条目.然后你必须加入新的.这不是一件轻而易举的事.

然后它使查询更简单(也许更快).有三个主要的数据库查询,你会做什么:输出所有TagsItem,绘制一个标签云,并选择一个标签名称的所有项目.

一个项目的所有标签:

3-表:

SELECT Tag.Title 
  FROM Tag 
  JOIN ItemTag ON Tag.TagID = ItemTag.TagID
 WHERE ItemTag.ItemID = :id

2-表:

SELECT Tag.Title
FROM Tag
WHERE Tag.ItemID = :id

标签云:

3-表:

SELECT Tag.Title, count(*)
  FROM Tag
  JOIN ItemTag ON Tag.TagID = ItemTag.TagID
 GROUP BY Tag.Title

2-表:

SELECT Tag.Title, count(*)
  FROM Tag
 GROUP BY Tag.Title

一个标签的项目:

3-表:

SELECT Item.*
  FROM Item
  JOIN ItemTag ON Item.ItemID = ItemTag.ItemID
  JOIN Tag ON ItemTag.TagID = Tag.TagID
 WHERE Tag.Title = :title

2-表:

SELECT Item.*
  FROM Item
  JOIN Tag ON Item.ItemID = Tag.ItemID
 WHERE Tag.Title = :title

但也有一些缺点:它可能需要在数据库中占用更多空间(这可能导致更多的磁盘操作更慢)并且没有规范化可能导致不一致.

size参数不是那么强大,因为标签的本质是它们通常非常小,所以尺寸增加不是很大.有人可能会争辩说,标签标题的查询在一个只包含每个标签一次的小表中要快得多,这肯定是正确的.但是考虑到不必加入的节省以及你可以为它们建立一个好的索引的事实可以很容易地弥补这一点.这当然在很大程度上取决于您使用的数据库的大小.

不一致的论点也有点没有实际意义.标签是自由文本字段,没有预期的操作,如'重命名所有标签'foo"到"bar"'.

所以tldr:我会选择双表解决方案.(事实上​​我要去.我发现这篇文章是否有反对它的有效论据.)


这样您就无法创建"未使用"的标签,因此必须在项目上执行"添加标签"功能.另一种方法是,"添加标签"功能可以独立执行

3> Nick Retalla..:

如果您正在使用支持map-reduce的数据库,例如couchdb,则在纯文本字段或列表字段中存储标记确实是最好的方法.例:

tagcloud: {
  map: function(doc){ 
    for(tag in doc.tags){ 
      emit(doc.tags[tag],1) 
    }
  }
  reduce: function(keys,values){
    return values.length
  }
}

使用group = true运行此命令将按标记名称对结果进行分组,甚至返回遇到标记的次数计数.它与计算文本中单词的出现次数非常相似.


+1很高兴看到一些NoSQL实现.

4> David Schmit..:

使用单个格式化文本列[1]存储标记,并使用功能强大的全文搜索引擎对其进行索引.否则,在尝试实现布尔查询时,您将遇到扩展问题.

如果需要有关标记的详细信息,可以在增量维护的表中跟踪它,也可以运行批处理作业来提取信息.

[1]有些RDBMS甚至提供了一种原生数组类型,它可能更适合存储而不需要解析步骤,但可能会导致全文搜索出现问题.



5> Mark Biek..:

我总是将标签保存在一个单独的表中,然后有一个映射表.当然,我从未做过大规模的任何事情.

拥有"标签"表和地图表使得生成标签云非常简单,因为您可以轻松地将SQL组合在一起以获取标签列表,其中包含每个标签使用频率的计数.


如果你不使用映射表,这就更容易了:)
推荐阅读
mobiledu2402851203
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有