How to delete large data of table in SQL without log?

匿名 (未验证) 提交于 2019-12-03 02:11:02

问题:

I have a large data table. There are 10 million records in this table.

What is the best way for this query

   Delete LargeTable where readTime < dateadd(MONTH,-7,GETDATE()) 

回答1:

  1. If you are Deleting All the rows in that table the simplest option is to Truncate table, something like

    TRUNCATE TABLE LargeTable GO 

    Truncate table will simply empty the table, you cannot use WHERE clause to limit the rows being deleted and no triggers will be fired.

  2. On the other hand if you are deleting more than 80-90 Percent of the data, say if you have total of 11 Million rows and you want to delete 10 million another way would be to Insert these 1 million rows (records you want to keep) to another staging table. Truncate this Large table and Insert back these 1 Million rows.

  3. Or if permissions/views or other objects which has this large table as their underlying table doesnt get affected by dropping this table you can get these relatively small amount of the rows into another table drop this table and create another table with same schema and import these rows back into this ex-Large table.

  4. One last option I can think of is to change your database's Recovery Mode to SIMPLE and then delete rows in smaller batches using a while loop something like this..

    DECLARE @Deleted_Rows INT; SET @Deleted_Rows = 1;   WHILE (@Deleted_Rows > 0)   BEGIN    -- Delete some small number of rows at a time      DELETE TOP (10000)  LargeTable       WHERE readTime < dateadd(MONTH,-7,GETDATE())    SET @Deleted_Rows = @@ROWCOUNT; END 

and dont forget to change the Recovery mode back to full and I think you have to take a backup to make it fully affective (the change or recovery modes).



回答2:

@m-ali answer is right but also keep in mind that logs could grow a lot if you don't commit the transaction after each chunk and perform a checkpoint. This is how I would do it and take this article http://sqlperformance.com/2013/03/io-subsystem/chunk-deletes as reference, with performance tests and graphs:

DECLARE @Deleted_Rows INT; SET @Deleted_Rows = 1;   WHILE (@Deleted_Rows > 0)   BEGIN     BEGIN TRANSACTION     -- Delete some small number of rows at a time      DELETE TOP (10000)  LargeTable       WHERE readTime < dateadd(MONTH,-7,GETDATE())       SET @Deleted_Rows = @@ROWCOUNT;     COMMIT TRANSACTION    CHECKPOINT -- for simple recovery model END 


回答3:

You can also use GO + how many times you want to execute the same query.

DELETE TOP (10000)  [TARGETDATABASE].[SCHEMA].[TARGETTABLE]  WHERE readTime < dateadd(MONTH,-1,GETDATE()); -- how many times you want the query to repeat GO 100 


回答4:

@Francisco Goldenstein, just a minor correction. The COMMIT must be used after you set the variable, otherwise the WHILE will be executed just once:

DECLARE @Deleted_Rows INT; SET @Deleted_Rows = 1;  WHILE (@Deleted_Rows > 0) BEGIN     BEGIN TRANSACTION      -- Delete some small number of rows at a time     DELETE TOP (10000)  LargeTable      WHERE readTime < dateadd(MONTH,-7,GETDATE())      SET @Deleted_Rows = @@ROWCOUNT;      COMMIT TRANSACTION     CHECKPOINT -- for simple recovery model  END 


回答5:

This variation of M.Ali's is working fine for me. It deletes some, clears the log and repeats. I'm watching the log grow, drop and start over.

DECLARE @Deleted_Rows INT; SET @Deleted_Rows = 1; WHILE (@Deleted_Rows > 0)   BEGIN    -- Delete some small number of rows at a time     delete top (100000) from InstallLog where DateTime between '2014-12-01' and '2015-02-01'     SET @Deleted_Rows = @@ROWCOUNT;     dbcc shrinkfile (MobiControlDB_log,0,truncateonly); END 


回答6:

If you are willing (and able) to implement partitioning, that is an effective technique for removing large quantities of data with little run-time overhead. Not cost-effective for a once-off exercise, though.



回答7:

You can delete small batches using a while loop, something like this:

DELETE TOP (10000)  LargeTable  WHERE readTime < dateadd(MONTH,-7,GETDATE()) WHILE @@ROWCOUNT > 0 BEGIN     DELETE TOP (10000)  LargeTable      WHERE readTime < dateadd(MONTH,-7,GETDATE()) END 


回答8:

I was able to delete 19 million rows from my table of 21 million rows in matter of minutes. Here is my approach.

If you have a auto-incrementing primary key on this table, then you can make use of this primary key.

  1. Get minimum value of primary key of the large table where readTime < dateadd(MONTH,-7,GETDATE()). (Add index on readTime, if not already present, this index will anyway be deleted along with the table in step 3.). Lets store it in a variable 'min_primary'

  2. Insert all the rows having primary key > min_primary into a staging table (memory table if no. of rows is not large).

  3. Drop the large table.

  4. Recreate the table. Copy all the rows from staging table to main table.

  5. Drop the staging table.



回答9:

Another use:

SET ROWCOUNT 1000 -- Buffer  DECLARE @DATE AS DATETIME = dateadd(MONTH,-7,GETDATE())  DELETE LargeTable  WHERE readTime < @DATE WHILE @@ROWCOUNT > 0 BEGIN    DELETE LargeTable  WHERE readTime < @DATE END SET ROWCOUNT 0 

Optional;

If transaction log is enabled, disable transaction logs.

ALTER DATABASE dbname SET RECOVERY SIMPLE; 


回答10:

Shorter syntax

select 1 WHILE (@@ROWCOUNT > 0) BEGIN   DELETE TOP (10000) LargeTable    WHERE readTime < dateadd(MONTH,-7,GETDATE()) END 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!