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 有多慢?的主要内容,如果未能解决你的问题,请参考以下文章

对单个字段的结果进行去重,用distinct执行效率快,还是用group by快

SQL 查询 - 太慢有多慢?

[CNBETA]动图告诉你 光速到底有多慢?

一行机器指令感受下内存操作到底有多慢

数组旋转中的超时问题。这个解决方案的速度有多慢?

Redis 的 keys 命令你知道有多慢吗?