Peformance Probleme bei Abfrage von redundanten Fragen

Hi,

um in einer Tabelle Redundante Daten zu finden verwende ich folgende Abfrage, allerdings ist diese äußerst langsam:

SELECT * FROM tab_test WHERE (feld1 IS NULL AND feld2 IS NULL AND feld3 IS NULL) OR (feld1 AND feld2 AND feld3) IN (SELECT feld1, feld2, feld3 FROM tab_test GROUP BY feld1 HAVING COUNT(*) > 1);

Nur wenn alle Felder gleich sind, sollen Daten ausgegeben werden. Erst erfolgt die Prüfung, ob in einer Zeile die Daten alle nicht null sind. Anschließend wird überprüft, ob Daten in den einzelenen Feldern mehrmals vorkommen.
Durch diese Gestaltung der Abfrage müssen aber die Felder immer einzeln komplett in der Tabelle durchgegangen werden. Gibt es eine Möglichkeit dies über Indizierung oder anderen Ansätze möglich ist.

Ein “Multicolumn Index” bringt nur Vorteile, wenn viele Datensatze die Testbedingung mehrfach haben, ansonsten heißt der Aufwand n^2 Datensätze testen.



mfg

fristo

Wie kann man es dann beschleunigen?

Also einige Felder hätten eine große Anzahl an gleich vorkommender Daten.

Mir stellt sich die Frage, was Du erreichen willst. Möglicherweise willst Du ja den ‘Schrott’ bereinigen und dann wäre Lutz Donnerhacke: de.comp.datenbanken.misc FAQ für Dich wohl interessant.

Oder ist es Absicht, redundante Daten zu halten?

Andreas

Die Daten sollen gehalten werden, es geht nur um die Information wieviele Redundanten Daten sich in der DB befinden.

Dann wirst Du wohl basteln müssen. Brauchst Du diese Anfrage oft, dann könnten TRIGGER, die Dir eine extra Statistik führen, helfen. Aber ganz allgemein: wenn redundante Daten in den Tabellen sind, würde ich nicht nach einer Verwaltung dieser nachdenken, sondern über deren Verzicht.

Andreas

Das mit den redundanten Daten ist mir schon klar, dass sowas nicht in eine DB gehört… die Motivation ist hier eine ganz andere, aber die tut hier nichts zur Sache. Es geht halt nur um das wie.

Ich versucge gerade das ganze mit Inner Join zu lösen, aber da kommt bei mir nich ganz das gleiche Resultat raus.

Vielleicht wäre es zielführend, mal die Tabelle und das korrekte Select zu zeigen. Das aus dem ersten beitrag funzt nicht…

Andreas

Mir erschließt sich noch immer nicht, warum Du so umständlich (und falsch) das abfragst. Wie schon gesagt, vielleicht wäre es FÜR DICH zielführend, uns mal eine kleine Tabelle mit Daten zu zeigen und auch das, was Du sehen willst.

create table tab_test (feld1 int, feld2 int, feld3 int);


test=# insert into tab_test (select generate_Series(1,10000), generate_Series(1,10000), generate_Series(1,10000));
INSERT 0 10000
test=*# insert into tab_test (select generate_Series(5,10), generate_Series(5,10), generate_Series(5,10));
INSERT 0 6

test=*# select feld1, feld2, feld3 from tab_test group by feld1,feld2,feld3 having count(1) > 1;
 feld1 | feld2 | feld3
-------+-------+-------
     9 |     9 |     9
     8 |     8 |     8
    10 |    10 |    10
     5 |     5 |     5
     7 |     7 |     7
     6 |     6 |     6
(6 rows)

Das resultiert in einem einfachen Seq-Scan. Deine Query braucht da bestimmt a bissl mehr.

Andreas

Also ich verwende jetzt einen Inner Join um die Daten zu vergleichen, damit erreiche eine höherere Geschwindigkeit als mit einem Select der über das Kartesische Produkt geht.