DISTINCT 有多慢?
Posted
技术标签:
【中文标题】DISTINCT 有多慢?【英文标题】:How slow is DISTINCT? 【发布时间】:2009-01-12 05:32:21 【问题描述】:我可以选择为数据库结构编写两种不同的格式:
Article
-------
ArticleID int FK
Article_Tags
------------
ArticleTagID int FK
ArticleID int FK
TagText varchar(50)
或
Article
-------
ArticleID int PK
Article_Tags
------------
ArticleTagID int PK
ArticleID int FK
TagText varchar(50) FK
Tag
---
TagText varchar(50) PK
如果我想要数据库中所有标签的列表,我可以使用:
select distinct tagtext from article_tags
或:
select tagtext from tag
第一种情况很简单。如果我正确索引它,也许它会加快速度。第二个有点困难,因为我必须不断删除没有连接的标签。想象一个相当大的系统,这样会更好。
【问题讨论】:
【参考方案1】:无论哪种解决方案都能为您的应用程序带来最佳/最简洁的设计,我都会选择。如果您需要将数据直接附加到标签,那么单独的表格(即更规范化的解决方案)将是正确的。
我会警告不要过分担心两种提议的解决方案的性能差异,如果编制索引,差异可能微不足道(两者都是相当常见的用例,可以使用标准数据库技术轻松优化)。根据性能在提供的 2 个选项之间做出决定听起来像是过早的优化。
【讨论】:
【参考方案2】:我会选择
Article
-------
ArticleID int PK
Article_Tags
------------
ArticleTagID int PK
ArticleID int FK
TagId int FK
Tag
---
TagId int identity(1,1) PK
TagText varchar(50)
确实没有理由从一开始就将其非规范化。 (你的第一个和第二个版本没有标准化)
在单独的表中包含标签很好,如果没有不同的声明,获取唯一标签会更干净。
如果应用了正确的索引,如果 3 个选项中的任何一个的性能几乎相同,则性能明智。
【讨论】:
你确定第二个没有被规范化吗?【参考方案3】:选项 2 进行了一些修改。假设您将输入限制为标签表中包含的值,那么您就可以针对不同目的执行两个不同的查询。
第一个查询将为您提供所有当前使用的标签的唯一列表。
第二个查询将为您提供所有可能使用的标签,包括尚未使用的标签。
您最好使用标签 ID 并在 tag 和 article_tags 表之间建立关系。这将使选项二更有效,因为索引只是一个整数而不是字符串。
【讨论】:
整数比字符串更高效? 一般来说。视大小而定。 目前我有第二种情况,但使用的是 TagID int 和 Tagtext,每次查询后都必须删除所有使用过的标签,这很烦人。【参考方案4】:回答标题中的基本问题:DISTINCT
通常意味着对数据进行排序。根据索引,查询的结构和返回的数据量可能是免费的(标签文本上的正确索引,ORDER BY tagtext
,小返回集)或不是(缺少索引,订单无关,大量返回集)。
【讨论】:
错了,只要提供明显的索引就不会排序。而且 DISTINCT 会非常有效 - dbms 知道如何从一个值的开头跳到下一个值。 这就是为什么我说“取决于索引 [...] 这可能是免费的(标签文本上的正确索引 [...]”【参考方案5】:维护两个表的开销不太可能成为搞乱简单设计的合理权衡。
如果您真的担心的话,可以简单地双向测试它,但根据我的丰富经验,毫无疑问这是真的。
【讨论】:
我可能会在单独的线程上执行更新/插入查询,因为它们不是关键任务以上是关于DISTINCT 有多慢?的主要内容,如果未能解决你的问题,请参考以下文章