2011-03-17 72 views
4

我收到了一个使用distinct关键字的SQL查询。当我尝试运行查询时,至少需要一分钟时间连接两个包含数十万条记录的表,并实际返回一些内容。SQL不同的关键字使性能下降?

然后我拿出了鲜明的,它在0.2秒内回来。独特的关键字是否真的让事情变得糟糕?

编辑:这里的查询

 

SELECT Distinct 
c.username, o.orderno, o.totalcredits, o.totalrefunds, 
o.recstatus, o.reason 

from management.contacts c 
join management.orders o 
on (c.custID = o.custID) 
where o.recDate > to_date('2010-01-01', 'YYYY/MM/DD') 
+2

你可以发布实际查询吗?根据我的经验,添加不同的关键字往往是纠正写得不好的查询的黑客。 – 2011-03-17 15:32:39

+0

坦率地说,我实际上并没有明白这个独特陈述的目的,而那个写这个陈述的人早已不在了... – MxyL 2011-03-17 15:47:38

+0

@Keikoku:查询是否返回不同数量的行,并且没有区别? – 2011-03-17 15:51:29

回答

5

是的,如使用DISTINCT会(有时根据评论)导致结果进行排序。对数百条记录进行排序需要时间。

尝试GROUP BY尝试GROUP BY所有列,它有时可能会导致查询优化器选择更高效的算法(至少在Oracle中我注意到显着的性能增益)。

+2

只是一个小小的附注:它不一定是通过排序结果来完成的。数据库可以自由应用任何它认为很好的策​​略来计算不同的行。 Oracle可以使用索引或散列,具体取决于哪些列应该是不同的。两者都不会导致排序步骤。但如果涉及到排序,那么这可能会相当昂贵。 – 2011-03-17 15:36:45

+0

@a_horse_with_no_name,(甚至更小的一面不在旁注中):hash也是一个索引。如此授予,不需要排序,但建立索引是。 – Unreason 2011-03-17 16:11:29

+0

@不理由:哈希不会对结果进行排序。这就是我想指出的。并且索引扫描不是必需的排序 – 2011-03-17 19:45:10

2

DISTINCT的用途是修剪所有选定列的结果集中的重复记录。

  • 如果任何选定的列在加入后都是唯一的,您可以删除DISTINCT。
  • 如果您不知道,但您知道所选列的值的组合是唯一的,那么可以丢弃DISTINCT。

实际上,通常情况下,如果设计合理的数据库,您很少需要DISTINCT,而在这种情况下,您所做的是(?)显然您需要它。但是,RDBMS不可能让它变得偶然,并且必须建立索引结构来建立它。

通常情况下,当人们不确定JOIN和表之间的关系时,通常会发现DISTINCT。

此外,在讨论纯关系数据库的类中,结果应该是一个适当的集合(没有重复元素=记录)时,您可以发现人们坚持DISTINCT以保证此属性为理论目的正确性。有时候这会渗入生产系统。

+0

放置DISTINCT是否是常见做法?我快速浏览了由同一个人编写的一些其他查询,并且他们中的每一个都使用DISTINCT,即使他查询的列中保留了添加到表中的每个条目的唯一编号。在这种情况下,这个数字是不需要的,但也许我应该把它折腾起来以保证唯一性。 – MxyL 2011-03-17 16:34:44

+0

不,它不应该是通常的做法。它杀死了性能(除非查询规划者可以确定它是多余的;我不知道oracle做得如何)。你应该知道你的联接的基数,列的唯一性,你应用的条件和你期望的结果,如果你需要它的话。 – Unreason 2011-03-17 16:50:21

0

您可以尝试这样做一团:

SELECT c.username, 
     o.orderno, 
     o.totalcredits, 
     o.totalrefunds, 
     o.recstatus, 
     o.reason 
    FROM management.contacts c, 
     management.orders o 
    WHERE c.custID = o.custID 
    AND o.recDate > to_date('2010-01-01', 'YYYY-MM-DD') 
GROUP BY c.username, 
     o.orderno, 
     o.totalcredits, 
     o.totalrefunds, 
     o.recstatus, 
     o.reason 

还要验证,如果你对有指数o.recDate

3

鲜明总是衬托了警钟,我 - 这通常表示糟糕的桌面设计或不确定自己的开发人员。它用于删除重复的行,但如果连接正确,则很少需要它。是的,使用它的成本很高。

订单表的主键是什么?假设它是orderno那么这应该足以保证没有重复。如果是别的,那么你可能需要做更多的查询,但是你应该把它作为消除这些差异的目标! ;-)

另外你提到查询在运行时需要一段时间来检查行数 - 通常可以更快地将整个查询包装在“select(count)(from)()”中,尤其是如果你会得到大量的行返回。显然,你正在测试。;-)

最后,请确保您已将订单表上的custID编入索引(也可能是recDate)。

+0

是的,我发现了使用不同的原因,这是因为他们想要一起加入所有的订单和客户,但结果是重复的订单,因为某些原因,多个记录是针对包含不相关信息的单个订单进行的到这个查询。但计数小费很好,似乎有600万条记录。 – MxyL 2011-03-18 13:26:03