Frage

Dies ist ein Abenteuer gewesen. Ich begann mit der Looping doppelten Abfrage in meine vorherige Frage , aber jede Schleife würde 17 Millionen Datensätze aller gehen , bedeutet, dass es Wochen dauern würde, (nur *select count * from MyTable* läuft mein Server 4.30 Minuten dauert mit MSSQL 2005). Ich schimmerten Informationen von dieser Seite und in diesem Post .

Und haben bei der Abfrage unten angekommen. Die Frage ist, ist dies die richtige Art der Abfrage auf 17 Millionen Datensätze für jede Art von Leistung zu laufen? Wenn dies nicht der Fall, was ist?

SQL-Abfrage:

DELETE tl_acxiomimport.dbo.tblacxiomlistings
WHERE RecordID in 
(SELECT RecordID
    FROM tl_acxiomimport.dbo.tblacxiomlistings
    EXCEPT
    SELECT RecordID
    FROM (
        SELECT RecordID, Rank() over (Partition BY BusinessName, latitude, longitude,           Phone ORDER BY webaddress DESC, caption1 DESC, caption2 DESC ) AS Rank
    FROM tl_acxiomimport.dbo.tblacxiomlistings
    ) al WHERE Rank = 1)
War es hilfreich?

Lösung

Sieht der Auswertungsplan helfen würde.

Ist das machbar?

SELECT m.*
into #temp
FROM tl_acxiomimport.dbo.tblacxiomlistings m 
inner join (SELECT RecordID, 
                   Rank() over (Partition BY BusinessName, 
                                             latitude,  
                                             longitude,            
                                             Phone  
                                ORDER BY webaddress DESC,  
                                         caption1 DESC,  
                                         caption2 DESC ) AS Rank
              FROM tl_acxiomimport.dbo.tblacxiomlistings
           ) al on (al.RecordID = m.RecordID and al.Rank = 1)

truncate table tl_acxiomimport.dbo.tblacxiomlistings

insert into tl_acxiomimport.dbo.tblacxiomlistings
     select * from #temp

Andere Tipps

Etwas ist mit Ihrer DB, Server, Speicher oder eine Kombination davon. 04.30 für eine ausgewählte Zählung * scheint sehr hoch.

ein DBCC_SHOWCONTIG Run, um zu sehen, wie fragmentiert Tisch ist, dies eine große Leistung getroffen über die Größe einer Tabelle führen kann.

, auch durch RyanKeeter zum Kommentar hinzufügen auf, die Show Plan laufen und ob es irgendwelche Tabellenscans einen Index für das PK-Feld erstellen, die auf dieser Tabelle.

Wäre es nicht einfacher sein zu tun:

DELETE tl_acxiomimport.dbo.tblacxiomlistings
WHERE RecordID in 
(SELECT RecordID
   FROM (
        SELECT RecordID,
            Rank() over (Partition BY BusinessName,
                                  latitude,
                                  longitude,
                                  Phone
                         ORDER BY webaddress DESC,
                                  caption1 DESC,
                                  caption2 DESC) AS Rank
        FROM tl_acxiomimport.dbo.tblacxiomlistings
        )
  WHERE Rank > 1
  )

Führen Sie diese in Query Analyzer:

SET SHOWPLAN_TEXT ON

Dann Query Analyzer fragen Sie Ihre Abfrage auszuführen. Statt die Abfrage von ausgeführt wird, SQL Server eines Abfrage-Plan erzeugen und es in der Ergebnismenge gesetzt.

Zeigen Sie uns den Abfrageplan.

17 Millionen Datensätze ist nichts. Wenn es 04.30 Uhr dauert nur eine ausgewählte Zählung zu tun (*), dann gibt es ein ernstes Problem, wahrscheinlich entweder Mangel in der Server-Speicher verbunden ist oder ein wirklich alter Prozessor.

Für die Leistung, fixieren Sie die Maschine. Pump it bis zu 2 GB. RAM ist so billig in diesen Tagen, dass die Kosten weit weniger als die Zeit.

Ist der Prozessor oder Disk Dreschen, wenn diese Abfrage geht? Wenn nicht, dann blockiert etwas die Anrufe. In diesem Fall könnten Sie die Datenbank im Single-User-Modus für die Zeit setzen es dauert, die Bereinigung ausgeführt werden.

So können Sie alle Datensätze sind zu löschen, die nicht den ersten Platz sind? Es könnte sich lohnen, einen Join gegen eine Top-1 Unter Abfrage zu vergleichen (die auch im Jahr 2000 funktionieren könnte, als Rang 2005 und oben nur)

Sie benötigen alle Duplikate in einem einzigen Vorgang entfernen? Ich gehe davon aus, dass Sie irgendeine Art von Housekeeping Aufgabe sind Vorformen, könnten Sie in der Lage sein, es stückweise zu tun.

Im Grunde genommen einen Cursor erstellen, die alle Datensätze (dirty read) Schleifen und entfernt Betrogenen für jeden. Es wird viel langsamer insgesamt, aber jeder Betrieb wird relativ gering sein. Dann wird Ihr Hauswirtschaft wird eine konstante Hintergrundaufgabe, statt einer nächtlichen Batch.

Der Vorschlag oben in eine temporäre Tabelle wählen Sie zuerst die beste Wahl ist. Man könnte auch so etwas wie verwenden:

set rowcount 1000

, bevor Sie löschen ausgeführt wird. Es wird nicht mehr ausgeführt, nachdem es die 1000 Zeilen löscht. Dann ist es wieder laufen und wieder, bis Sie 0 erhalten Datensätze gelöscht.

Wenn ich es richtig bekommen Sie abfragen, ist die gleiche wie

DELETE tl_acxiomimport.dbo.tblacxiomlistings
FROM
    tl_acxiomimport.dbo.tblacxiomlistings allRecords
    LEFT JOIN (   
        SELECT RecordID, Rank() over (Partition BY BusinessName, latitude, longitude, Phone ORDER BY webaddress DESC, caption1 DESC, caption2 DESC ) AS Rank
        FROM tl_acxiomimport.dbo.tblacxiomlistings
        WHERE Rank = 1) myExceptions
    ON allRecords.RecordID = myExceptions.RecordID
WHERE
    myExceptions.RecordID IS NULL

ich denke, dass schneller laufen soll, neige ich dazu, mit „IN“ Klausel zugunsten zu vermeiden, des Joins, soweit möglich.

Sie können tatsächlich die Geschwindigkeit testen und sicher die Ergebnisse durch einfaches SELECT * oder SELECT COUNT(*) auf der FROM-Teil wie z aufrufen.

SELECT *
FROM
    tl_acxiomimport.dbo.tblacxiomlistings allRecords
    LEFT JOIN (   
        SELECT RecordID, Rank() over (Partition BY BusinessName, latitude, longitude, Phone ORDER BY webaddress DESC, caption1 DESC, caption2 DESC ) AS Rank
        FROM tl_acxiomimport.dbo.tblacxiomlistings
        WHERE Rank = 1) myExceptions
    ON allRecords.RecordID = myExceptions.RecordID
WHERE
    myExceptions.RecordID IS NULL

Das ist ein weiterer Grund, warum ich würde der Ansatz JOIN bevorzugen Ich hoffe, das hilft

Das sieht gut aus, aber Sie könnten betrachten Sie Ihre Daten in eine temporäre Tabelle auswählen und das in Ihrer Lösch-Anweisung. Ich habe diese enorme Leistungssteigerungen bemerkt zu tun, anstatt sie alle in dieser eine Abfrage zu tun.

Denken Sie daran, wenn Sie eine große löschen tun es am besten zuerst eine gute Unterstützung haben. (Und ich kopieren auch in der Regel die gelöschten Datensätze an einen anderen Tisch nur für den Fall, ich brauche sie sofort zu erholen.)

Andere als die Verwendung von gestutzt, wie vorgeschlagen, ich habe zum Löschen vielen Zeilen aus einer Tabelle das beste Glück mit dieser Vorlage hat. Ich erinnere mich Hand nicht aus, aber ich denke, die Transaktion half mit der Log-Datei, um zu verhindern wächst - wenn auch ein weiterer Grund gewesen sein mag - nicht sicher. Und ich in der Regel die Transaktionsprotokollierung Methode wechseln einfach vorbei, bevor so etwas wie dies zu tun:

SET ROWCOUNT 5000
WHILE 1 = 1
BEGIN
    begin tran
            DELETE FROM ??? WHERE ???
            IF @@rowcount = 0
            BEGIN
               COMMIT
               BREAK
            END
    COMMIT
END
SET ROWCOUNT 0
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top