14.01.2015 Views

Eric lippert - Amazon Web Services

Eric lippert - Amazon Web Services

Eric lippert - Amazon Web Services

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

09<br />

Housekeeping databases<br />

If you have transactional tables where records get inserted very<br />

frequently and unless you remove older records from the table, you<br />

run out of space within weeks; then it is a challenge to periodically<br />

purge such tables, without bringing down the tables. If you have<br />

a 24x7 website, then it becomes very difficult to find a slot where<br />

you can take an outage and do a purge that takes on an average of<br />

15-30 mins to finish. During purge operations, the table gets locked<br />

and all other queries on that table times out. So, you need to find<br />

a way to purge records consuming the least amount of database<br />

resource.<br />

delete from @BatchIds<br />

Set @rowCount = @@rowCount;<br />

Print ‘Deleted ‘ + convert(varchar(10), @rowcount) + ‘<br />

rows...’<br />

waitfor delay ‘00:00:05’<br />

End;<br />

go<br />

Checkpoint 30; -- simple recovery, if full - put tlog<br />

backup here<br />

Go<br />

There are various ways to do this but we found the following<br />

approach having the least footprint on the database:<br />

Declare @batchsize int; Set @batchsize = 1000;<br />

set transaction isolation level read uncommitted; set<br />

nocount on;<br />

declare @temp_rows_to_delete table (ID int primary key)<br />

insert into @temp_rows_to_delete select ID FROM<br />

VeryLargeTable WHERE ID < 4000<br />

Declare @rowCount int; Set @rowCount = 1;<br />

declare @BatchIds table (id int primary key)<br />

While @rowCount > 0<br />

Begin<br />

-- Pick the IDs to delete and remove them from #temp_rows<br />

delete top(@batchsize) from @temp_rows_to_delete<br />

OUTPUT deleted.ID into @BatchIds<br />

delete from VeryLargeTable WHERE ID IN (SELECT ID FROM @<br />

BatchIds)<br />

The idea here is to do a steady small batch of delete at a time until<br />

all the records we want to purge are deleted. This query can go<br />

on for hours, not a problem. But during that time, there will be no<br />

significant stress on the database to cause other queries to timeout<br />

or degrade significantly.<br />

First we set the isolation level. This is absolutely a key thing to<br />

do. This isolation level tells SQL Server that the following query<br />

does not need locking. It can read dirty data, does not matter. So,<br />

there’s no reason for SQL Server to lock records in order to ensure<br />

the query gets properly committed data. Unless you are a bank, you<br />

should put this in all your stored procs and you will see 10 times<br />

better throughput sometimes from your database, for read queries.<br />

Next we read the row IDs from the source table and store in a table<br />

variable. This is the only time we are going to do a SELECT on the<br />

source table so that SQL Server does not have to scan the large<br />

table again and again.<br />

Then we keep picking 1000 row IDs at a time and delete the rows<br />

from the table. After each delete, we give SQL Server 5 seconds to<br />

rest and flush the logs.<br />

10<br />

Tuning database indexes<br />

Over the time, data in tables get fragmented as data gets inserted,<br />

updated and deleted. If you leave the tables alone, the indexes will<br />

get slower and slower resulting in slower queries. If you have<br />

millions of records on a table and you start having significant<br />

fragmentation on the tables, over the time, queries will get so slow<br />

that they will start timing out.<br />

In order to keep the tables fast and lean, you need to regularly<br />

rebuild the indexes. Here’s a SQL snippet that will run through<br />

all the indexes on the database and see if the indexes are heavily<br />

fragmented. If they are, then it will issue an index rebuild on them.<br />

Ref: http://www.mssqltips.com/sqlservertip/1165/managing-sqlserver-database-fragmentation/<br />

10 | DNCmagazine www.dotnetcurry.com

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!