• Don't try to delete all the rows at once. Even in simple recovery mode, all the activity must be logged for the duration of the statement. Drop batches of rows until there are no more remaining. The optimum batch size depends on row size, server configuration, etc., and may be arrived at through testing.

    WHILE 1=1 BEGIN

    DELETE TOP (10000) FROM dbo.table WHERE id > 20877065 ;

    IF @@ROWCOUNT = 0 BREAK ;

    END

    An alternate technique is to copy the data you want to keep into a temp table, then truncate the main table and reload it. The TRUNCATE operation is minimally logged, although both record-copying operations will be logged. If much more data is being deleted than being kept, this is a better approach. This assumes there are no foreign key complications, but you may want to drop foreign keys on this table and recreate them after the delete no matter which version you use.

    SELECT * INTO #table FROM dbo.table WHERE id <= 20877065 ;

    IF @@ROWCOUNT > {expected row count} BEGIN

    TRUNCATE TABLE dbo.table ;

    INSERT INTO dbo.table WITH(TABLOCKX) SELECT * FROM #table ;

    IF @@ROWCOUNT > {expected row count}

    DROP TABLE #table ;

    END

    Other considerations:

    The DELETE TOP (N) version works best if "WHERE id > 20877065" is referencing a clustered primary key. If for example you're keeping the first million rows of a fifty-million row table, and id is not the clustered key, it will probably have to table scan through those first million rows every iteration before finding ten thousand rows to delete. Repeat 4900 times. If id is the clustered primary key, it will be able to find the rows to delete very quickly.

    If the table is a heap (no clustered index or key), then the TRUNCATE TABLE version is emphatically the best choice.