我们最近发现我们的某个系统存在性能问题,我认为我有修复但我不确定我的理解是否正确。
在最简单的形式中,我们有一个表blah
,我们根据一个关键字段累积各种值。基本形式是:
recdate date
rectime time
system varchar(20)
count integer
accum1 integer
accum2 integer
还有更多的累加器,但它们都是相同的形式。主键由recdate
,rectime
和system
组成。
随着值被收集到表中,给定recdate/rectime/system
的计数递增,并且该键的值被添加到累加器。这意味着可以使用accumN / count
获得平均值。
现在我们还有一个关于该表的视图,如下所示:
create view blah_v (
recdate, rectime, system, count,
accum1,
accum2
) as select distinct
recdate, rectime, system, count,
value (case when count > 0 then accum1 / count end, 0),
value (case when count > 0 then accum2 / count end, 0)
from blah;
换句话说,视图给出了累加器的平均值而不是总和。它还确保在计数为零的情况下我们不会得到除零(这些记录做存在且我们不允许删除它们所以不要打扰告诉我他们是垃圾 - 你正在向合唱团讲道。)
我们注意到之间的时差:
select distinct recdate from XX
根据我们使用表格还是视图而有很大差异。我说的是表的差异是1秒,视图的差异是27秒(有100K行)。
我们实际上将其追溯到select distinct
。似乎正在发生的是DBMS实际上正在加载所有行并对其进行排序以便删除重复项。这是公平的,这是我们愚蠢地告诉它要做的事情。
但我很确定视图包含主键的每个组件这一事实意味着无论如何都不可能有重复项。我们已经验证了这个问题,因为如果我们创建另一个没有distinct的视图,它的执行速度与底层表相同。
我只是想确认一下,如果select distinct
包含所有主要关键组件,则{{1}}不能重复。如果是这样,那么我们可以简单地改变视图。
答案 0 :(得分:4)
在这种情况下,DISTINCT对您没有任何好处,因为由于基础表上的PRIMARY KEY约束,您的不同字段已经保证是唯一的。您可以尝试将视图重写为:
create view blah_v (
recdate, rectime, system, count,
accum1,
accum2
) as select
recdate, rectime, system, count,
case when count > 0 then accum1 / count else 0 end,
case when count > 0 then accum2 / count else 0 end,
from blah;
分享并享受。
答案 1 :(得分:3)
是的,当包含所有主要关键元素时,要求distinct
结果毫无意义。
表的主键约束已经排除了这些列的重复,但是您的DBMS仍将处理元组以确保它们是不同的。
答案 2 :(得分:2)
如果视图直接从单个表中选择,并且所选列的子集在表上是唯一的,那么所选行的值在值中是唯一的,而distinct是多余的。