SQL Batched Delete

后端 未结 9 1880
星月不相逢
星月不相逢 2021-02-20 04:29

I have a table in SQL Server 2005 which has approx 4 billion rows in it. I need to delete approximately 2 billion of these rows. If I try and do it in a single transaction, th

相关标签:
9条回答
  • 2021-02-20 05:03

    What distinguishes the rows you want to delete from those you want to keep? Will this work for you:

    while exists (select 1 from your_table where <your_condition>)
    delete top(10000) from your_table
    where <your_condition>
    
    0 讨论(0)
  • 2021-02-20 05:05

    Sounds like this is one-off operation (I hope for you) and you don't need to go back to a state that's halfway this batched delete - if that's the case why don't you just switch to SIMPLE transaction mode before running and then back to FULL when you're done?

    This way the transaction log won't grow as much. This might not be ideal in most situations but I don't see anything wrong here (assuming as above you don't need to go back to a state that's in between your deletes).

    you can do this in your script with smt like:

    ALTER DATABASE myDB SET RECOVERY FULL/SIMPLE
    

    Alternatively you can setup a job to shrink the transaction log every given interval of time - while your delete is running. This is kinda bad but I reckon it'd do the trick.

    0 讨论(0)
  • 2021-02-20 05:06

    Here is my example:

    -- configure script
    -- Script limits - transaction per commit (default 10,000)
    -- And time to allow script to run (in seconds, default 2 hours)
    --
    DECLARE @MAX INT
    DECLARE @MAXT INT
    --
    -- These 4 variables are substituted by shell script.
    --
    SET @MAX = $MAX
    SET @MAXT = $MAXT
    SET @TABLE = $TABLE
    SET @WHERE = $WHERE
    
    -- step 1 - Main loop
    DECLARE @continue INT
    -- deleted in one transaction
    DECLARE @deleted INT
    -- deleted total in script
    DECLARE @total INT
    SET @total = 0
    DECLARE @max_id INT, @start_id INT, @end_id INT, @interval INT
    SET @interval = @MAX
    SELECT @start_id = MIN(id), @max_id = MAX(id) from @TABLE
    SET @end_id = @start_id + @interval
    
    -- timing
    DECLARE @start DATETIME
    DECLARE @now DATETIME
    DECLARE @timee INT
    SET @start = GETDATE()
    -- 
    SET @continue = 1
    IF OBJECT_ID (N'EntryID', 'U') IS NULL 
    BEGIN
        CREATE TABLE EntryID (startid INT)
        INSERT INTO EntryID(startid) VALUES(@start_id)
    END
        ELSE
    BEGIN
        SELECT @start_id = startid FROM EntryID
    END
    
    
    WHILE (@continue = 1 AND @start_id <= @max_id)
    BEGIN
    
        PRINT 'Start issued:   ' + CONVERT(varchar(19), GETDATE(), 120)
        BEGIN TRANSACTION
            DELETE 
            FROM @TABLE
            WHERE id BETWEEN @start_id AND @end_id AND @WHERE
            SET @deleted = @@ROWCOUNT
        UPDATE EntryID SET EntryID.startid = @end_id + 1
        COMMIT
        PRINT 'Deleted issued: ' + STR(@deleted) + ' records. ' + CONVERT(varchar(19), GETDATE(), 120) 
        SET @total = @total + @deleted
        SET @start_id = @end_id + 1
        SET @end_id = @end_id + @interval
        IF @end_id > @max_id
            SET @end_id = @max_id
    
        SET @now = GETDATE()
        SET @timee = DATEDIFF (second, @start, @now)
        if @timee > @MAXT
        BEGIN
        PRINT 'Time limit exceeded for the script, exiting'
        SET @continue = 0
        END
    --    ELSE
    --    BEGIN
    --      SELECT @total 'Removed now', @timee 'Total time, seconds'   
    --    END
    END
    
    SELECT @total 'Removed records', @timee 'Total time sec' , @start_id 'Next id', @max_id 'Max id', @continue 'COMPLETED? '
    SELECT * from EntryID next_start_id
    
    GO
    
    0 讨论(0)
提交回复
热议问题