考虑这3个表结构。哪个会最好地执行这些查询。
Article
-------
ArticleID int
Article_Tag
------------
ArticleTagID int
ArticleID int
TagID int
Tag
---
TagID int
TagText varchar(50)
Article
-------
articleID int
Article_Tag
-----------
articleTagID int
articleID int
tag varchar(50)
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
答案 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
表的合成密钥。您应该使用复合主键(ArticleId
,TagId
)。
所以,我说上面提到的小调整#1。
答案 5 :(得分:0)
我会选择结构2,可能只是简单地调用Article_Tag表 - 标签。
答案 6 :(得分:0)
具有AUTO_INCREMENT PK的表格不会缩放。忘掉TagID作为INTEGER,并将其类型替换为BINARY(16),就足以用于TagText的MD5校验和。
使用适当的缓存层,您的SQL查询将不需要TagText列。