How to efficiently delete rows while NOT using Truncate Table in a 500,000+ rows table

后端 未结 8 1421
死守一世寂寞
死守一世寂寞 2020-11-30 01:30

Let\'s say we have table Sales with 30 columns and 500,000 rows. I would like to delete 400,000 in the table (those where \"toDelete=\'1\'\").

8条回答
  •  南方客
    南方客 (楼主)
    2020-11-30 01:50

    I'll leave my answer here, since I was able to test different approaches for mass delete and update (I had to update and then delete 125+mio rows, server has 16GB of RAM, Xeon E5-2680 @2.7GHz, SQL Server 2012).

    TL;DR: always update/delete by primary key, never by any other condition. If you can't use PK directly, create a temp table and fill it with PK values and update/delete your table using that table. Use indexes for this.

    I started with solution from above (by @Kevin Aenmey), but this approach turned out to be inappropriate, since my database was live and it handles a couple of hundred transactions per second and there was some blocking involved (there was an index for all there fields from condition, using WITH(ROWLOCK) didn't change anything).

    So, I added a WAITFOR statement, which allowed database to process other transactions.

    deleteMore:
    WAITFOR DELAY '00:00:01'
    DELETE TOP(1000) FROM MyTable WHERE Column1 = @Criteria1 AND Column2 = @Criteria2 AND Column3 = @Criteria3
    IF @@ROWCOUNT != 0
        goto deleteMore
    

    This approach was able to process ~1.6mio rows/hour for updating and ~0,2mio rows/hour for deleting.

    Turning to temp tables changed things quite a lot.

    deleteMore:
    SELECT TOP 10000 Id /* Id is the PK */
      INTO #Temp 
      FROM MyTable WHERE Column1 = @Criteria1 AND Column2 = @Criteria2 AND Column3 = @Criteria3 
    
    DELETE MT
      FROM MyTable MT
      JOIN #Temp T ON T.Id = MT.Id 
    
    /* you can use IN operator, it doesn't change anything
     DELETE FROM MyTable WHERE Id IN (SELECT Id FROM #Temp)
    
     */
    IF @@ROWCOUNT > 0 BEGIN
        DROP TABLE #Temp
        WAITFOR DELAY '00:00:01'
        goto deleteMore
    END ELSE BEGIN
        DROP TABLE #Temp
        PRINT 'This is the end, my friend'
    END
    

    This solution processed ~25mio rows/hour for updating (15x faster) and ~2.2mio rows/hour for deleting (11x faster).

提交回复
热议问题