Frage

Mit SQL Server 2005.

Ich führe einen riesigen Löschen ohne Wo -Klauseln durch. Es entspricht im Grunde einer Tischtabellenerklärung - außer dass ich nicht abschneide. Das Problem ist, dass der Tisch riesig ist - 10 Millionen Zeilen, und es dauert über eine Stunde. Gibt es eine Möglichkeit, es schneller zu machen, ohne:

  • Verwenden von Kürzungen
  • Indexen deaktivieren oder fallen lassen?

Der T-Log befindet sich bereits auf einer separaten Festplatte.

Alle Vorschläge willkommen!

War es hilfreich?

Lösung

Was Sie tun können, ist, dass Löschung wie folgt stapelte:

SELECT 'Starting' --sets @@ROWCOUNT
WHILE @@ROWCOUNT <> 0
    DELETE TOP (xxx) MyTable

Wo xxx beispielsweise 50000 ist

Eine Modifikation davon, wenn Sie einen sehr hohen Prozentsatz an Zeilen entfernen möchten ...

SELECT col1, col2, ... INTO #Holdingtable
           FROM MyTable WHERE ..some condition..

SELECT 'Starting' --sets @@ROWCOUNT
WHILE @@ROWCOUNT <> 0
    DELETE TOP (xxx) MyTable WHERE ...

INSERT MyTable (col1, col2, ...)
           SELECT col1, col2, ... FROM #Holdingtable

Andere Tipps

Sie können die obere Klausel verwenden, um dies leicht zu erledigen:

WHILE (1=1)
BEGIN
    DELETE TOP(1000) FROM table
    IF @@ROWCOUNT < 1 BREAK
END

Ich stimme den Vorschlägen zu, Ihre Deletten in verwaltbare Brocken zu stapeln, wenn Sie nicht in der Lage sind, Truncate zu verwenden, und ich mag den Drop/Erstellen von Vorschlägen für seine Originalität, aber ich bin gespannt auf den folgenden Kommentar in Ihrer Frage:

Es entspricht im Grunde genommen einer Kürzungstabellenerklärung - Außer ich darf nicht verkürzt werden

Ich vermute, der Grund für diese Einschränkung hat mit der Sicherheit zu tun, die gewährt werden muss, um eine Tabelle direkt abzuschneiden, und die Tatsache, dass Sie es ermöglichen würden, andere Tabellen als die zu verkürzen, mit der Sie sich befassen.

Angenommen, dies ist der Fall, frage ich mich, ob ein gespeichertes Verfahren erstellt wird, das die Tischtabelle verwendet und "ausführen als" als praktikable Alternative angesehen wird, um Sicherheitsrechte zu geben, die für die direkte Abschneidung der Tabelle erforderlich sind.

Hoffentlich würde Ihnen dies die Geschwindigkeit verleihen, die Sie benötigen, und gleichzeitig die Sicherheitsbedenken, die Ihr Unternehmen bei der Hinzufügung Ihres Kontos zur Rolle des DB_DDLADMIN hat, ausgeht.

Ein weiterer Vorteil der Verwendung eines gespeicherten Verfahrens auf diese Weise besteht darin, dass das gespeicherte Verfahren selbst gesperrt werden kann, sodass nur bestimmte Konto (n) es verwenden dürfen.

Wenn dies aus irgendeinem Grund keine akzeptable Lösung ist und Sie, dass die Daten in dieser Tabelle entfernt werden müssen zu einer geplanten Zeit jeden Tag.

Hoffe das hilft!

Außer verkürzt .. nur in Chargen löschen können Ihnen helfen.

Sie können die Tabelle fallen lassen und sie mit allen Einschränkungen und Indizes nachbilden. In Management Studio haben Sie die Möglichkeit, eine Tabelle zu skript zu schriften und zu erstellen. Daher sollte es sich um eine triviale Option handeln. Dies jedoch nur, wenn Sie DDL -Aktionen ausführen dürfen, was ich sehe, ist es nicht wirklich eine Option.

Da diese Frage eine so wichtige Referenz ist, veröffentliche ich diesen Code, der mir wirklich geholfen hat, das Löschen mit Schleifen und auch Nachrichten innerhalb einer Schleife zu verstehen, um den Fortschritt zu verfolgen.

Die Abfrage wird aus geändert Dies doppelte Frage. Gutschrift an @Rlf Für die Abfragebasis.

CREATE TABLE #DelTest (ID INT IDENTITY, name NVARCHAR(128)); -- Build the test table
INSERT INTO #DelTest (name) SELECT name FROM sys.objects;  -- fill from system DB
SELECT COUNT(*) TableNamesContainingSys FROM #deltest WHERE name LIKE '%sys%'; -- check rowcount
go
DECLARE @HowMany INT;
DECLARE @RowsTouched INT;
DECLARE @TotalRowCount INT;
DECLARE @msg VARCHAR(100);
DECLARE @starttime DATETIME 
DECLARE @currenttime DATETIME 

SET @RowsTouched = 1; -- Needs to be >0 for loop to start
SET @TotalRowCount=0  -- Total rows deleted so far is 0
SET @HowMany = 5;     -- Variable to choose how many rows to delete per loop
SET @starttime=GETDATE()

WHILE @RowsTouched > 0
BEGIN
   DELETE TOP (@HowMany)
   FROM #DelTest 
   WHERE name LIKE '%sys%';

   SET @RowsTouched = @@ROWCOUNT; -- Rows deleted this loop
   SET @TotalRowCount = @TotalRowCount+@RowsTouched; -- Increment Total rows deleted count
   SET @currenttime = GETDATE();
   SELECT @msg='Deleted ' + CONVERT(VARCHAR(9),@TotalRowCount) + ' Records. Runtime so far is '+CONVERT(VARCHAR(30),DATEDIFF(MILLISECOND,@starttime,@currenttime))+' milliseconds.'
   RAISERROR(@msg, 0, 1) WITH NOWAIT;  -- Print message after every loop. Can't use the PRINT function as SQL buffers output in loops.  

END; 
SELECT COUNT(*) TableNamesContainingSys FROM #DelTest WHERE name LIKE '%sys%'; -- Check row count after loop finish
DROP TABLE #DelTest;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top