2010-03-22 8 views
6

Wenn ich versuche, einen eindeutigen Index für eine große Tabelle zu erstellen, erhalte ich einen eindeutigen Contraint-Fehler. Der eindeutige Index ist in diesem Fall ein zusammengesetzter Schlüssel aus 4 Spalten.Oracle: Identifizieren von Duplikaten in einer Tabelle ohne Index

Gibt es eine effiziente Möglichkeit, die Duplikate andere als zu identifizieren:

select col1, col2, col3, col4, count(*) 
from Table1 
group by col1, col2, col3, col4 
having count(*) > 1 

Der erklären Plan oben zeigt vollständige Tabelle scannen mit extrem hohen Kosten, und wollen einfach nur zu finden, wenn es eine andere Möglichkeit ist.

Danke!

+0

http://www.remote-dba.cc/oracle_tips_duplicate_rows.htm –

Antwort

7

Versuchen Sie zunächst, einen nicht eindeutigen Index für diese vier Spalten zu erstellen. Das wird O (n log n) Zeit benötigen, wird aber auch die Zeit reduzieren, die benötigt wird, um 0 (0)zu O (n log n) durchzuführen.

Sie sind hier ein wenig gebunden - egal wie Sie es schneiden, die gesamte Tabelle muss mindestens einmal eingelesen werden. Der Algorithmus wird in O (n) Zeit ausgeführt, es sei denn, der Abfrageoptimierer ist schlau genug, um einen temporären Index/Tabelle zu erstellen.

+3

Nachdem Sie Ihr nicht eindeutiges Problem gelöst haben, können Sie die eindeutige Integritätsbedingung mit dem von Ihnen erstellten nicht eindeutigen Index erzwingen.Sie können keinen eindeutigen Index erstellen, während Sie einen nicht eindeutigen Index für die gleichen Spalten haben. Wenn Sie also wirklich einen eindeutigen Index erstellen möchten, erstellen Sie Ihren nicht eindeutigen Index als create index t_ix in table1 (col1, col2, col3) , col4,1); Mit dem Literal am Ende wird es Sie nicht stoppen, später den eindeutigen Index für Spalte1, Spalte2, Spalte3, Spalte4 zu erstellen und dann den nicht eindeutigen Index zu löschen –

+0

Alle Antworten zeigten an, dass es keinen einfachen Ausweg aus diesem Problem gibt. Aber diese Antwort gab mir auch einen Ansatz, also wählte ich dies als die beste Antwort auf mein Problem. Danke Jeff. –

1

Da es für diese Spalten keinen Index gibt, müsste diese Abfrage einen vollständigen Tabellenscan durchführen - keine andere Möglichkeit, dies wirklich zu tun, es sei denn, eine oder mehrere dieser Spalten sind bereits indiziert.

Sie könnten den Index als nicht eindeutigen Index erstellen und dann die Abfrage ausführen, um die doppelten Zeilen zu identifizieren (die nach der Indexerstellung sehr schnell sein sollten). Aber ich bezweifle, dass die kombinierte Zeit des Erstellens des nicht eindeutigen Indexes, der dann die Abfrage ausführt, weniger wäre, als nur die Abfrage ohne den Index auszuführen.

0

Ich glaube nicht, dass es leider einen schnelleren Weg gibt.

1

In der Tat müssen Sie nach einem Duplikat jeder einzelnen Zeile in einer Tabelle suchen. Keine Möglichkeit, dies effektiv ohne einen Index zu tun.

2

Mit der EXCEPTIONS INTO-Klausel können Sie die doppelten Zeilen abfangen.

Wenn Sie nicht bereits über eine AUSNAHMEN Tabelle eine der bereitgestellten Skript erstellen müssen:

SQL> @$ORACLE_HOME/rdbms/admin/ultexcpt.sql 

Jetzt können Sie versuchen, eine eindeutige Einschränkung wie diese

alter table Table1 
add constraint tab1_uq UNIQUE (col1, col2, col3, col4) 
exceptions into exceptions 
/

scheitern Dies wird zu schaffen, sondern Jetzt enthält Ihre EXCEPTIONS-Tabelle eine Liste aller Zeilen, deren Schlüssel Duplikate enthalten, die von ROWID identifiziert werden. Das gibt Ihnen eine Grundlage für die Entscheidung, was mit den Duplikaten geschehen soll (löschen, neu nummerieren, was auch immer).

bearbeiten

Wie andere haben darauf hingewiesen, Sie einmal die Kosten für das Scannen der Tabelle zu zahlen. Dieser Ansatz bietet Ihnen eine permanente Menge der duplizierten Zeilen und ROWID ist der schnellste Weg, um auf eine bestimmte Zeile zuzugreifen.

Verwandte Themen