Verwenden von SQL Server 2005.
Ich führe ein großes DELETE FROM ohne no-Klauseln durch. Es entspricht im Grunde einer TRUNCATE TABLE-Anweisung - außer dass ich TRUNCATE nicht verwenden darf. Das Problem ist, dass die Tabelle riesig ist - 10 Millionen Zeilen, und die Fertigstellung dauert über eine Stunde. Gibt es eine Möglichkeit, es schneller zu machen, ohne:
Das T-Log befindet sich bereits auf einer separaten Festplatte.
Anregungen willkommen!
Was Sie tun können, ist Batch-Löschungen wie folgt:
SELECT 'Starting' --sets @@ROWCOUNT
WHILE @@ROWCOUNT <> 0
DELETE TOP (xxx) MyTable
Wo xxx ist, sagen wir 50000
Eine Änderung davon, wenn Sie einen sehr hohen Prozentsatz von 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
Sie können die TOP-Klausel verwenden, um dies einfach zu erledigen:
WHILE (1=1)
BEGIN
DELETE TOP(1000) FROM table
IF @@ROWCOUNT < 1 BREAK
END
Ich bin mit den Vorschlägen einverstanden, Ihre Löschvorgänge in verwaltbare Blöcke zu stapeln, wenn Sie TRUNCATE nicht verwenden können, und ich mag den Drop/Create-Vorschlag für seine Originalität, aber ich bin gespannt auf den folgenden Kommentar in Ihrer Frage:
Es entspricht im Grunde einer TRUNCATE TABLE-Anweisung - außer ich darf TRUNCATE nicht verwenden
Ich vermute, der Grund für diese Einschränkung hängt mit der Sicherheit zusammen, die gewährt werden muss, um eine Tabelle direkt abzuschneiden, und mit der Tatsache, dass Sie damit andere als die von Ihnen betroffene Tabellen abschneiden können.
Unter der Annahme, dass dies der Fall ist, frage ich mich, ob die Erstellung einer gespeicherten Prozedur, die TRUNCATE TABLE verwendet und "EXECUTE AS" verwendet, als praktikable Alternative zur Gewährung von Sicherheitsrechten angesehen wird, die zum direkten Abschneiden der Tabelle erforderlich sind.
Dies gibt Ihnen hoffentlich die Geschwindigkeit, die Sie benötigen, und berücksichtigt gleichzeitig die Sicherheitsbedenken, die Ihr Unternehmen möglicherweise hat, wenn Sie Ihr Konto zur Rolle db_ddladmin hinzufügen.
Ein weiterer Vorteil der Verwendung einer gespeicherten Prozedur auf diese Weise besteht darin, dass die gespeicherte Prozedur selbst gesperrt werden kann, sodass nur bestimmte Konten sie verwenden dürfen.
Wenn dies aus irgendeinem Grund keine akzeptable Lösung ist und Sie die Daten in dieser Tabelle entfernen müssen, müssen Sie einmal am Tag/in der Stunde/usw. einen SQL Agent-Job erstellen, um die Tabelle abzuschneiden jeden Tag zu einer festgelegten Zeit.
Hoffe das hilft!
Außer abschneiden .. nur das Löschen in Stapeln kann Ihnen helfen.
Sie können die Tabelle löschen und natürlich mit allen Einschränkungen und Indizes neu erstellen. In Management Studio haben Sie die Möglichkeit, ein Skript zum Löschen und Erstellen einer Tabelle zu erstellen. Dies sollte daher eine triviale Option sein. Dies ist jedoch nur möglich, wenn Sie DDL-Aktionen ausführen dürfen. Ich sehe, dass dies keine Option ist.
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 das Versenden von Nachrichten innerhalb einer Schleife zu verstehen, um den Fortschritt zu verfolgen.
Die Abfrage wurde geändert von this 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 = @[email protected]; -- 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;