标签表的优化表结构

时间:2009-01-11 22:38:13

标签: sql

考虑这3个表结构。哪个会最好地执行这些查询。

结构1 - TagID为带有连接表的int

Article
-------
ArticleID int

Article_Tag
------------
ArticleTagID int
ArticleID int
TagID int

Tag
---
TagID int
TagText varchar(50)

结构2 - 仅在连接表中标记为字符串

Article
-------
articleID int

Article_Tag
-----------
articleTagID int
articleID int
tag varchar(50)

结构3 - 标记为PK

的文本
Article
-------
ArticleID int

Article_Tag
------------
ArticleTagID int
ArticleID int
Tag varchar(50)

Tag
---
Tag varchar(50)

示例查询:

Select articleID from Article a inner join Article_tag at on a.articleID = at.articleID and tag = 'apple'
Select tag from Tags -- or, for structure 2
Select distinct tag from article_tag

7 个答案:

答案 0 :(得分:5)

这取决于您是否希望能够全局更改标记文本。当然,您可以在UPDATE上发出广泛Article_Tag,但如果您需要能够执行此操作,那么只需更新Tag中的值就会更简单。有些服务器提供自动更新(例如SQL Server中的ON UPDATE CASCADE),但这些更新并不一定便宜(它仍然需要UPDATE许多行和任何索引定义。

但是如果你需要这个,那么Article_Tag中的文字应该会更快一些,因为它可以删除连接 - 很多次。显然,索引它等。

重复文字所需的额外空间是一个因素,但磁盘空间通常比更快的服务器便宜。

至于主键;除非你有其他数据需要存储,为什么你甚至需要这个表呢?您可以轻松地在DISTINCT使用Article_Tag,尤其是Tag应该被编入索引(因此这应该非常便宜)。 (编辑 Bill Karwin正确地指出了能够保留符合条件的标签的优点,而不仅仅是当前的标签。)

答案 1 :(得分:4)

使用TagText作为主键的优势在于您可以获得包含较少联接的文章标记:

SELECT * FROM Article_Tag WHERE Article_ID = ?

它的缺点是标记字符串比整数占用更多空间,因此Article_Tag及其索引的存储空间会更大。这会在磁盘上占用更多空间,并且还需要更多内存来缓存索引。

答案 2 :(得分:2)

我每次都去1。它已完全标准化,因为您使用的是合成PK,您可以使用单行更新来更改标记的名称。

否则唯一的优点是减少连接数。这是一项优化,我们都知道您应该只在测量后进行优化。如果你确定结构1不够快,你就不会问,对吧?

现在2和3之间并没有太大区别,但正如Bill Karwin所说,3在级联更新方面具有优势。更重要的是,额外的桌子什么都没有丢失。

所以我会说1.如果有一个可衡量的(即可证明的)性能问题那么3将是完全可以接受的。无论如何,以后迁移并不是很难。

答案 3 :(得分:0)

欢迎回来,谦虚。或者Localghost,或肖恩,或者你现在称自己。请记住,不再有黑客徽章,所以没有什么可以赢得这里:)

答案 4 :(得分:0)

您应该将代码中的TagText映射到TagId(并始终映射到内存缓存)并将预先映射的TagId传递到您的查询中。

也没有理由需要Article_Tag表的合成密钥。您应该使用复合主键(ArticleIdTagId)。

所以,我说上面提到的小调整#1。

答案 5 :(得分:0)

我会选择结构2,可能只是简单地调用Article_Tag表 - 标签

答案 6 :(得分:0)

具有AUTO_INCREMENT PK的表格不会缩放。忘掉TagID作为INTEGER,并将其类型替换为BINARY(16),就足以用于TagText的MD5校验和。

使用适当的缓存层,您的SQL查询将不需要TagText列。