2010-05-03 13 views
6

Wir haben vor kurzem ein Performance-Problem mit einem unserer Systeme entdeckt und ich denke, ich habe die Lösung, aber ich bin mir nicht sicher, ob mein Verständnis korrekt ist.Ist mein Verständnis von "Select distinct" korrekt?

In der einfachsten Form haben wir eine Tabelle blah, in der wir verschiedene Werte basierend auf einem Schlüsselfeld ansammeln. Das Grundformular ist:

recdate date 
rectime time 
system varchar(20) 
count  integer 
accum1 integer 
accum2 integer 

Es gibt viel mehr Akkumulatoren als das, aber sie sind alle von der gleichen Form. Der Primärschlüssel besteht aus recdate, rectime und system.

Während die Werte in der Tabelle gesammelt werden, wird der Zähler für eine gegebene recdate/rectime/system inkrementiert und die Werte für diesen Schlüssel werden den Akkumulatoren hinzugefügt. Das bedeutet, dass die Durchschnittswerte erhalten werden können, indem accumN/count verwendet wird.

Jetzt haben wir auch einen Blick auf diese Tabelle wie folgt angegeben:

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; 

Mit anderen Worten, gibt die Ansicht uns den Durchschnittswert der Akkumulatoren eher als die Summen. Es stellt auch sicher, dass wir keine Division durch Null in den Fällen erhalten, in denen die Zählung Null ist (diese Datensätze existieren und wir dürfen sie nicht entfernen, also mach dir keine Sorgen, mir zu sagen, dass sie Quatsch sind - du predigst dem Chor).

Wir haben festgestellt haben, dass die Zeitdifferenz zwischen Tun:

select distinct recdate from XX 

stark in Abhängigkeit davon variiert, ob wir die Tabelle oder die Ansicht verwenden. Ich spreche über den Unterschied, 1 Sekunde für die Tabelle und 27 Sekunden für die Ansicht (mit 100 K Zeilen).

Wir haben es tatsächlich zurück auf die select distinct verfolgt. Offensichtlich lädt das DBMS alle Zeilen und sortiert sie, um Duplikate zu entfernen. Das ist ehrlich gesagt, es ist das, was wir dumm gesagt haben.

Aber ich bin ziemlich sicher, die Tatsache, dass die Ansicht jede Komponente des Primärschlüssels enthält, bedeutet, dass es unmöglich ist, Duplikate sowieso zu haben. Wir haben das Problem validiert, da es, wenn wir eine andere Ansicht ohne distinct erstellen, mit der gleichen Geschwindigkeit wie die zugrunde liegende Tabelle arbeitet.

Ich wollte nur bestätigen, dass ein select distinct keine Duplikate haben kann, wenn es alle Primärschlüsselkomponenten enthält. Wenn das so ist, können wir einfach die Ansicht entsprechend ändern.

Antwort

3

Ja, es ist sinnlos, nach distinct Ergebnissen zu fragen, wenn alle Primärschlüsselelemente enthalten sind.

Die Primärschlüsselbedingung der Tabelle schließt bereits Duplikate in diesen Spalten aus, aber Ihr DBMS verarbeitet weiterhin die Tupel, um sicherzustellen, dass sie unterschiedlich sind.

2

Wenn die Ansicht direkt aus einer einzelnen Tabelle ausgewählt wird und eine Untergruppe ausgewählter Spalten in der Tabelle eindeutig ist, dann folgt daraus, dass die ausgewählten Zeilen in Werten eindeutig und distinct redundant sind.

4

In diesem Fall ist die DISTINCT nicht gut, weil Ihre eindeutigen Felder aufgrund der PRIMARY KEY-Einschränkung für die zugrunde liegende Tabelle bereits eindeutig sind.Sie könnten versuchen, die Ansicht wie folgt umzuschreiben:

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; 

Teilen und genießen.