原文来自:Then each went to his own home
原文作者:Philipp Keller
中文翻译:icyleaf

译者注:本文在涉及到专业术语或者译者表达不明白的地方均会保留原英文。

最近,在del.icio.us mailinglist(译者按:应该是美味书签的讨论版块。以下del.icio.us翻译为美味书签)上面发了一个问题:“有人知道美味书签的数据库设计吗?”。之后我得到了一些回复,所以我想把这部分东西的知识分享给大家。

疑问

当你要为一个书签添加你认为需要的一个或多个标签时(或日志或其他)其数据库是如何设计的?然后,执行查询时取消这些书签中标签的合集(union)或交集(intersection)。也能从搜索结果中减少一些标签。

大致有三种不同的解决方案:(注意:如果你开发了一个网站使得任何人都可以添加标签,而且是一个较大规模的网站则请务必看下其作者写的另外一篇文章:标签系统的性能测试)

“MySQLicious” 方法(solution)

在这个方法中仅架构了一个表,它是去规范化(denormalized)表。

这个类型被叫做“MySQLicious 方法(solution)”,因为MySQLicious使用这种结构可以把美味书签的数据导入到一个表中。

译者注:MySQLicious是一个把del.icio.us书签镜像到MySQL数据库中的工具。

交集(AND)

查询方式: “search+webservice+semweb”:

SELECT * FROM `delicious` WHERE tags LIKE "%search%" AND tags LIKE "%webservice%" AND tags LIKE "%semweb%"

合集(OR)

查询方式: “search|webservice|semweb”:

SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
OR tags LIKE "%webservice%"
OR tags LIKE "%semweb%" 

减少(Exclusion)

查询方式: “search+webservice-semweb”

SELECT *
FROM `delicious`
WHERE tags LIKE "%search%"
AND tags LIKE "%webservice%"
AND tags NOT LIKE "%semweb%" 

结论

优点:

  • 只用一个表。
  • 查询方式简单易懂。
  • 一次就能获得全文搜索结果,可能速度快一些。
  • 我猜测查询在基于良好的参数下是相当的 快(Peter Cooper的博客也提到:去规范化!去规范化!去规范化!) 慢的。全文搜索会稍微提速,我做了一个我的配置测试来验证它。
  • 在我随后的日志交待使用MySQL fulltext出来有关标签的事情。

缺点:

  • 每个书签的标签数量是有限的。通常情况下是在数据库中使用一个256字节的域(VCHAIR),否则,假设你用Text或类似的域,则速度将会慢下来。
  • 如果你注意了(就像Patrice那样)你会发现当你以“websearch”使用Like “%search”搜索标签时它也能搜索到,当你修改并使用Like “%search%”时你最终必须使用一个混乱的解决方法:在标签头添加一个空格,这样才能使其工作。

“Scuttle” 方法(solution)

分离(Scuttle)字段,并归类到两个表中。右图表“scCategories”是一个标签表,通过一个外来的ID链接书签表。

交集(AND)

查询方式:“bookmark+webservice+semweb”:

SELECT b.* FROM scBookmarks b, scCategories c WHERE c.bId = b.bId AND (c.category IN ('bookmark', 'webservice', 'semweb')) GROUP BY b.bId HAVING COUNT( b.bId )=3

首先,当搜索的标签为“bookmark”,“webservice“或“semweb”(例如:c.category IN ('bookmark', 'webservice', 'semweb'))时所有名为"bookmark"的标签都会被搜索,然后所有包含这三个标签的书签将筛选出来 (HAVING COUNT(b.bId)=3).

合集(OR)

查询方式:“bookmark|webservice|semweb”:
Just leave out the HAVING clause and you have union:

SELECT b.* FROM scBookmarks b, scCategories c WHERE c.bId = b.bId AND (c.category IN ('bookmark', 'webservice', 'semweb')) GROUP BY b.bId

减少(Exclusion)

查询方式:“bookmark+webservice-semweb”,意味着:bookmark AND webservice AND NOT semweb.

SELECT b. * FROM scBookmarks b, scCategories c WHERE b.bId = c.bId AND (c.category IN ('bookmark', 'webservice')) AND b.bId NOT IN (SELECT b.bId FROM scBookmarks b, scCategories c WHERE b.bId = c.bId AND c.category = 'semweb') GROUP BY b.bId HAVING COUNT( b.bId ) =2

省略掉 HAVING COUNT 会导致搜索方式变为“bookmark|webservice-semweb”.
信息来源:Rhomboid写的helping me out with this query.

结论

我猜测这个解决方案主要有利点是使得他更正常化,比第一个解决方案比较而言,好处在于可以为每一个书签添加无限数量的标签。

“Toxi” 方法(solution)

Toxi 提出了一个三个表的结构,通过表”tagmap“的书签和标签的n-to-m关联。每一个标签都可以在不同的书签一期使用,反之亦然。这种数据库结构也被用在Wordpress之中。

交集(AND)

查询方式:“bookmark+webservice+semweb”

SELECT b.* FROM tagmap bt, bookmark b, tag t WHERE bt.tag_id = t.tag_id AND (t.name IN ('bookmark', 'webservice', 'semweb')) AND b.id = bt.bookmark_id GROUP BY b.id HAVING COUNT( b.id )=3

合集(OR)

查询方式:“bookmark|webservice|semweb”

SELECT b.* FROM tagmap bt, bookmark b, tag t WHERE bt.tag_id = t.tag_id AND (t.name IN ('bookmark', 'webservice', 'semweb')) AND b.id = bt.bookmark_id GROUP BY b.id

减少(Exclusion)

查询方式:“bookmark+webservice-semweb”,意味:bookmark AND webservice AND NOT semweb.

SELECT b. * FROM bookmark b, tagmap bt, tag t WHERE b.id = bt.bookmark_id AND bt.tag_id = t.tag_id AND (t.name IN ('Programming', 'Algorithms')) AND b.id NOT IN (SELECT b.id FROM bookmark b, tagmap bt, tag t WHERE b.id = bt.bookmark_id AND bt.tag_id = t.tag_id AND t.name = 'Python') GROUP BY b.id HAVING COUNT( b.id ) =2

省略掉 HAVING COUNT 会导致搜索方式变为“bookmark|webservice-semweb”.
信息来源:Rhomboid写的helping me out with this query.

结论

优点:

  • 可以为每个标签节省额外的信息(描述,分类等)
  • 这是一个最正常化的解决方案(即,第三范式:3NF)

缺点:

  • 当修改或删除书签后,需要删除中间表的相应数据(When altering or deleting bookmarks you can end up with tag-orphans)。

如果你想要更复杂的查询,比如”(bookmarks OR bookmark) AND (webservice or WS) AND NOT (semweb or semanticweb)“这样的查询语句,我建议参见以下查询/计算过程:

  1. 为每一个标签出现在你的”“tag-query”时执行一个查询(Run a query for each tag appearing in your “tag-query”):SELECT b.id FROM tagmap bt, bookmark b, tag t WHERE bt.tag_id = t.tag_id AND b.id = bt.bookmark_id AND t.name = "semweb"
  2. 把每一个编号集从结果中导到一个数值里面(使用你喜欢的编码语言),这样可以缓存你想要的数组。
  3. 使用合集或交集或其他方式限制数组。

通过这种方式,你也可以查询"(del.icio.us|delicious)+(semweb|semantic_web)-search",这种类型的查询(即,括号内)利用去规范化的“MySQLicious solution”不能这样做。
这是最灵活的数据结构和我猜想它的效果相当好(即,使用一些缓存技术)。

2006年5月更新:这篇文章获得了大家的注视。我真的不是为此而准备的!看来大家不断的提到了他,甚至一些网站转载我的文章,我认为,这些不同方式的理论的知识应该归功于:MySQLicious, scuttle, Toxi以及所有参与并贡献的评论者(请务必阅读!)

p.s. 感谢Toxi发给我关于三个表结构的疑问,Benjamin Reitzammer为我指点的文章(一个很好的标签查询参考)和powerlinux提供的scuttle指引。

扩展阅读

    • Taglist: a mailing list dedicated to schemas with tagging
    • Tagschema: A blog dedicated to tagging schemas
    • Tag-related Queries on Snippets
    • Freetag is a php “library” with which you can add tags to whatever object you like. It actually uses the “toxi schema”.
    • Hammy gives an insight how he did his tagging system with “less DB and more code” (that is: regular expressions), interesting!
    • Brad Choate has got some ideas which tag queries should be possible
    • Feedmaker has written a sort of reply to this article

标签(Tag)的数据库设计相关推荐

  1. mysql 分类标签表设计_如何进行文章分类和标签的数据库设计

    几乎在所有web项目中,都涉及文章分类和标签的设计,应该说这是一个比较常见.典型的案例.站长并不保证我的思路就是最好的,只是分享出来大家一起交流一下,互相促进与提高. 我们假设的开发项目是一个博客系统 ...

  2. [SQL] 外卖系统数据库设计

    注意: 1.项目需求:小程序外卖系统,以美团,饿了么为参考. 2.表设计没有外键约束,设计是在程序中进行外键约束. 3.希望通过分享该数据库设计,获取大家的建议和讨论. SQL: 1 CREATE D ...

  3. 恭迎万亿级营销(圈人)潇洒的迈入毫秒时代 - 万亿user_tags级实时推荐系统数据库设计...

    标签 PostgreSQL , 标签 , 推荐系统 , 实时圈人 , 数组 , gin , gist , 索引 , rum , tsvector , tsquery , 万亿 , user , tag ...

  4. 权限管理系统数据库设计的简单构思

    最近在工作中接触到权限管理的设计,于是,自己在网上查阅了部分资料,再加上自己的一些思考,构思了一个简单的权限管理系统的数据库设计. RBAC与Tag 说到权限管理,一般都会想到基于角色的访问控制(Ro ...

  5. 文章分类标签数据库设计

    文章分类对应标签数据库设计 这是16 年写的文章.自己悠着看 几乎在大部分有管新闻列表项目中,都涉及文章与标签的设计,应该说比较常见.典型的例子.考虑了很多种办法,见识了三四种对应的关系,现在我来说一 ...

  6. QQ(腾讯)-群空间-数据库设计

    DatabaseName:QQ-群空间 Model:群相册.群共享.群论坛.群成员.留言板.公告.6个模块. Type:空间-群空间.论坛 1.B,数据库设计脚本(Database Design Sc ...

  7. 数据库设计的10个最佳实践

    作者 | Emily Williamson 译者 | 孙薇,责编 | 屠敏 出品 | CSDN(ID:CSDNnews) 以下为译文: 数据库是应用及计算机的核心元素,负责存储运行软件应用所需的一切重 ...

  8. datamodeler mysql_NavicatDataModeler-官方版-数据库设计工具(NavicatDataModeler)1.0.10官方特别版-独木成林...

    数据库设计工具(Navicat Data Modeler)很好玩喔,特别是逆向工程的功能.一直在看SQL,谁知道好的工具下开发这么轻松!Navicat Data Modeler 是一个强大的和符合成本 ...

  9. 电子商务(电销)平台中用户模块(User)数据库设计明细

    原文:电子商务(电销)平台中用户模块(User)数据库设计明细 以下是自己在电子商务系统设计中的订单模块的数据库设计经验总结,而今发表出来一起分享,如有不当,欢迎跟帖讨论~ 用户基础表(user_ba ...

最新文章

  1. Java学习笔记23
  2. 现在,用音频也能指挥GAN生成图像了
  3. 说说 Spring 的事务同步管理器
  4. 教你精确编写高质量高性能的MySQL语法
  5. 编译原理——实验壹——TINY语言的词法分析
  6. 大数据学习笔记12:搭建伪分布式Spark
  7. win10系统windows hello无法设置 windows hello设置开启教程
  8. pandas小记:pandas索引和选择
  9. Centos6.4系统局域网服务之DHCP
  10. Bind 一些有趣的东西 【未完待续】
  11. 【Java -- 设计模式】模板方法模式(Template Method)
  12. Excel构建决策分析模型
  13. 驾考你准备好了吗 之 交通标志、标线篇
  14. java pv uv_使用Spark计算PV、UV
  15. 提供计算机网络通信功能,在计算机网络中,通信子网的主要作用是___ 答案:提供计算机网络的通信功能...
  16. Windows系统内置测试工具(winsat)
  17. 今天给大家分享的案例就是关于电影的啦,我们一起来看看IMDBtop10000的电影排行榜数据
  18. 数据库的查询、视图和游标
  19. 网易微专业 UI设计师
  20. 此图片来自微信公众平台 未经允许不可引用

热门文章

  1. 浅析基于TCP/IP的一对多通信1——TCP/IP是什么鬼?
  2. 开机Non-system disk or disk error,replace and strike any key when ready,的解决.
  3. 2018/4/18赛前心情调整
  4. 互联网企业风生水起 四大商业模式彰显生机
  5. QImage/QPixmap加载图片失败(宽和高都为0)的两种解决方法
  6. App Store政策网址
  7. 【Elastic Stack上】Elastic Search快速入门,让你对ELK日志架构不再困惑
  8. 三流Mayavi操作-Mayav-2.1.1-图形控制函数 Figure handling functions
  9. 支持多语言网站实现方案
  10. 正视代码Review,养成良好的编程习惯