Frage

Wir haben eine Abfrage einige Zeilen aus der Tabelle auf einem ID-Feld (Primärschlüssel) auf der Basis zu entfernen. Es ist eine ziemlich einfache Abfrage:

delete all from OUR_TABLE where ID in (123, 345, ...)

Das Problem ist, Anzahl ids sehr groß sein kann (z. B. 70k), so dass die Abfrage dauert eine lange Zeit. Gibt es eine Möglichkeit, dies zu optimieren? (Wir verwenden sybase - wenn es ankommt).

War es hilfreich?

Lösung

Betrachten Sie diese in den Reihen laufen. Eine Schleife läuft 1000 Datensätze zu einer Zeit kann viel schneller als eine Abfrage, die alles und zusätzlich tut, wird der Tisch auf einer Strecke so lange an andere Benutzer nicht halten gesperrt.

Wenn Sie Kaskade haben löschen (und viele Fremdschlüsseltabellen betroffen sind) oder löst beteiligt sind, können Sie in noch kleinere Chargen fahren müssen. Sie werden experiement haben, um zu sehen, welche die beste Zahl für Ihre Situation ist. Ich habe Tabellen, in denen ich in Chargen von 100 und anderen löschen musste, wo 50000 (Glück, in diesem Fall, wie ich eine Million Datensätze zu löschen) gearbeitet.

Aber in jeder selbst würde ich meine Schlüsselwerte setzen, die ich in eine temporäre Tabelle löschen möchten, und löschen Sie von dort aus.

Andere Tipps

Es gibt zwei Möglichkeiten, Aussagen wie diese zu machen ausführen:

  1. Erstellen Sie eine neue Tabelle, und kopieren Sie alle, aber die Zeilen zu löschen. Tauschen Sie die Tabellen danach (alter table name ...) Ich schlage vor, geben einen es versuchen, auch wenn es blöd klingt. Einige Datenbanken sind viel zu kopieren schneller als bei zu löschen.

  2. Partitionieren der Tabellen. Erstellen N Tabellen und eine Ansicht verwenden, um sie zu einem verbinden. Sortieren Sie die Zeilen in verschiedenen Tabellen durch das Löschkriterium gruppiert. Die Idee ist, eine ganze Tabelle zu löschen, anstatt einzelne Zeilen zu löschen.

Ich frage mich, eine IN-Klausel mit 70K Elementen in ihm, wenn das Parsen ein Problem ist. Haben Sie mit einem eine temporäre Tabelle statt beitreten versucht?

Can Sybase Griff 70K Argumente in IN-Klausel? Alle Datenbanken Ich arbeitete mit haben einige Begrenzung der Anzahl der Argumente für IN Klausel. Zum Beispiel hat Oracle Grenze um 1000.

Können Sie subselect statt IN-Klausel erstellen? Das wird SQL verkürzen. das könnte für eine so große Anzahl von Werten in IN-Klausel Vielleicht helfen. So etwas wie folgt aus:

  DELETE FROM OUR_TABLE WHERE ID IN 
        (SELECT ID FROM somewhere WHERE some_condition)

Löschen große Anzahl von Datensätzen kann mit einigen Interventionen in der Datenbank beschleunigt werden, wenn Datenbankmodell zulässt. Hier sind einige Strategien:

  1. Sie können die Dinge beschleunigen, indem Indizes, Löschen von Datensätzen löschen und Indizes wieder neu zu erstellen. Dies wird Rebalancing Index Bäume beseitigen, während Aufzeichnungen zu löschen.

    • fallen alle Indizes auf Tabelle
    • Löschen von Datensätzen
    • neu erstellen Indizes
    • , wenn Sie viele Beziehungen zu dieser Tabelle haben, versuchen Einschränkungen zu deaktivieren, wenn Sie absolut sicher sind, dass Löschbefehl wird jede Integritätsbedingung nicht brechen. Löschen geht viel schneller, weil Datenbank nicht Integrität werden überprüft. Enable Einschränkungen nach löschen.
    • Integritätsbedingungen deaktivieren, deaktivieren Check-Einschränkungen
    • Löschen von Datensätzen
    • enable Einschränkungen
    • disable Trigger auf dem Tisch, wenn Sie irgendwelche und wenn Ihre Geschäftsregeln zulassen, dass. Löschen von Datensätzen, dann Trigger aktivieren.

    • Schließlich tun, wie andere vorgeschlagen - eine Kopie der Tabelle machen, die Zeilen enthält, die gelöscht werden sollen, nicht, dann original fallen, Kopie umbenennen und Integritätsbedingungen neu erstellen, wenn es welche gibt.

Ich würde versuchen, Kombination von 1, 2 und 3. Wenn das nicht funktioniert, dann 4. Wenn alles langsam, ich für größere Box aussehen würde -. Mehr Speicher, schnellere Festplatten

Finden Sie heraus, was die Leistung wird mit up!

In vielen Fällen können Sie eine der angebotenen Lösungen verwenden. Aber es könnte andere sein (basierend auf Oracle Wissen, so die Dinge auf andere Datenbanken unterschiedlich sein Edit:. Gerade gesehen, dass Sie sybase erwähnt):

  • Möchten Sie auf dieser Tabelle Fremdschlüssel haben? Stellt sicher, dass die aufgerufene ids indiziert
  • Haben Sie Indizes für diese Tabelle? Es könnte sein, dass vor löschen Droping und neu zu erstellen, nachdem der Lösch könnte schneller sein.
  • Überprüfen Sie den Ausführungsplan. Ist es mit einem Index, in dem ein vollständiger Tabellenscan schneller sein könnte? Oder umgekehrt? TIPPS könnte helfen,
  • anstelle einer Auswahl in new_table wie oben einer Tabelle erstellen vorgeschlagen, wie wählen Sie könnten sogar schneller sein.

Aber denken Sie daran:. Finden Sie heraus, was zuerst die Leistung unter Verwendung von bis ist

Wenn Sie DDL-Anweisungen verwenden, stellen Sie sicher, dass Sie verstehen und akzeptieren, die Folgen auf Transaktionen und Sicherungen haben könnten.

Versuchen

Sortieren die ID Du vorbei in „in“ in der gleichen Reihenfolge wie die Tabelle oder Index gespeichert ist. Sie können dann mehr Treffer auf der Disk-Cache erhalten.

Setzen Sie die ID werden in eine temporäre Tabelle gelöscht, die die Ids in der gleichen Reihenfolge wie der Haupttabelle sortiert ist, kann die Datenbank tun lassen eine einfache über der Haupttabelle gescannt.

Sie könnten versuchen, mehr als eine Verbindung mit und die Arbeit über die Verbindungen spiting, um alle CPUs auf dem Datenbankserver zu verwenden, um jedoch zu denken, was Schlösser herausgenommen werden usw. zuerst.

Ich denke auch, dass die temporäre Tabelle wahrscheinlich die beste Lösung ist.

Wenn Sie sind ein „Löschen von .. wo ID in (wählen Sie ID aus ...)“ tun es immer noch langsam mit großen Abfragen sein kann, though. Ich so vorschlagen, dass Sie löschen mit einem Join -. Viele Menschen wissen nicht, über diese Funktionalität

So, da dieses Beispiel Tabelle:

    -- set up tables for this example
    if exists (select id from sysobjects where name = 'OurTable' and type = 'U')
        drop table OurTable
    go

    create table OurTable (ID integer primary key not null)
    go
    insert into OurTable (ID) values (1)
    insert into OurTable (ID) values (2)
    insert into OurTable (ID) values (3)
    insert into OurTable (ID) values (4)
    go

Wir können dann unseren Lösch Code schreiben, wie folgt:

    create table #IDsToDelete (ID integer not null)
    go
    insert into #IDsToDelete (ID) values (2)
    insert into #IDsToDelete (ID) values (3)
    go
    -- ... etc ...
    -- Now do the delete - notice that we aren't using 'from'
    -- in the usual place for this delete
    delete OurTable from #IDsToDelete
       where OurTable.ID = #IDsToDelete.ID
    go
    drop table #IDsToDelete
    go
    -- This returns only items 1 and 4
    select * from OurTable order by ID
    go

Gibt es einen Verweis auf Lösch Kaskade our_table haben?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top