<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5 : asp.net sqlserver</title><link>http://msmvps.com/blogs/omar/archive/tags/asp.net+sqlserver/default.aspx</link><description>Tags: asp.net sqlserver</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Cleanup inactive anonymous users from ASP.NET Membership Tables</title><link>http://msmvps.com/blogs/omar/archive/2007/03/25/cleanup-inactive-anonymous-users-from-asp-net-membership-tables.aspx</link><pubDate>Sun, 25 Mar 2007 18:39:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:709188</guid><dc:creator>omar</dc:creator><slash:comments>31</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=709188</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2007/03/25/cleanup-inactive-anonymous-users-from-asp-net-membership-tables.aspx#comments</comments><description>
&lt;p&gt;ASP.NET 2.0 Websites that allow anonymous visit and anonymous user profile have a unique challenge to cleanup unused data which is generated by anonymous users who never come back. Every first visit is creating one anonymous user, page setup, and other user specific content. If the user never comes back, it still remains in the database permanently. It is possible user might come back within a day, or a week or a month. But there’s no guaranty if user will ever come back or not. Generally sticky users are max 30% of the total users who come to most websites. So, you end up with 70% unused data which are never needed. All these requires cleanup, otherwise the database keeps growing uncontrollably and gets slower and slower. This cleanup operation is humongous for busy websites. Think about deleting millions of rows from several tables, one after another while maintaining foreign key constraints. Also the cleanup operation needs to run while the site is running, without hampering site&amp;#39;s overall performance. The whole operation results in heavily fragmented index and space in the MDF file. The log file also becomes enormous in order to keep track of the transactions. Hard drives get really hot and start sweating furiously. While the CPU keeps smiling having nothing to do with it, it’s really painful to watch SQL Server go through this every day. Unless you clean up the database and maintain its size under control; you can&amp;#39;t keep up with SQL Server’s RAM and Disk IO requirement.&amp;nbsp; 
&lt;/p&gt;

&lt;p&gt;When a user visits the site, Asp.net Membership Provider updates the LastActivityDate of aspnet_users table. From this field, I can find out how long the user has been idle. The IsAnonymous bit field tells me whether the user account is anonymous or registered. If it is registered, no need to worry. But if it is anonymous and more than 30 days old, I can be sure that the user will never come back because the cookie has already expired. If you repeatedly logout from your start page, all cookie related to the site gets cleared. That means you are producing one new anonymous user record during each log out. That anonymous record is never used because you will soon log in to have your customized pages back and then you will log out again. This will result in another anonymous user account which again becomes useless as soon as you log in. 
&lt;/p&gt;

&lt;p&gt;Here’s how the whole cleanup process works: 
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find out the users which are old enough to be discarded 
&lt;/li&gt;

&lt;li&gt;Find out the pages user has 
&lt;/li&gt;

&lt;li&gt;Delete all the widget instances on those pages 
&lt;/li&gt;

&lt;li&gt;Then delete those pages 
&lt;/li&gt;

&lt;li&gt;Remove rows from child tables related to aspnet_users like aspnet_profile, aspnet_UsersInRoles, aspnet_PersonalizationPerUser. Remove rows for users to be deleted 
&lt;/li&gt;

&lt;li&gt;Remove the users from aspnet_users 
&lt;/li&gt;

&lt;li&gt;Pray that you did not accidentally remove any good user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the giant DB script which does it all. I have put enough inline comment so that you can understand what the script is doing:&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:&lt;/span&gt; &lt;span class="rem"&gt;-- Number of days after which we give users &amp;#39;bye bye&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:&lt;/span&gt; &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @Days &lt;span class="kwrd"&gt;int&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:&lt;/span&gt; &lt;span class="kwrd"&gt;SET&lt;/span&gt; @Days = 14&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:&lt;/span&gt; &lt;span class="rem"&gt;-- No of users to delete per run. If it&amp;#39;s too high, database will get stuck&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:&lt;/span&gt; &lt;span class="rem"&gt;-- for a long time. If it&amp;#39;s too low, you will end up having more trash than&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:&lt;/span&gt; &lt;span class="rem"&gt;-- you can cleanup&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:&lt;/span&gt; &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @NoOfUsersToDelete &lt;span class="kwrd"&gt;int&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   9:&lt;/span&gt; &lt;span class="kwrd"&gt;SET&lt;/span&gt; @NoOfUsersToDelete = 1000&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  11:&lt;/span&gt; &lt;span class="rem"&gt;-- Create temporary tables which holds the users and pages to delete&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:&lt;/span&gt; &lt;span class="rem"&gt;-- As the user and the page is used to find out other tables, instead&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  13:&lt;/span&gt; &lt;span class="rem"&gt;-- of running SELECT ID FORM ... repeatedly, it&amp;#39;s better to have them&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:&lt;/span&gt; &lt;span class="rem"&gt;-- in a temp table&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  15:&lt;/span&gt; &lt;span class="kwrd"&gt;IF&lt;/span&gt;  &lt;span class="kwrd"&gt;EXISTS&lt;/span&gt; (&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; * &lt;span class="kwrd"&gt;FROM&lt;/span&gt; sys.objects &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; object_id = OBJECT_ID(N&lt;span class="str"&gt;&amp;#39;[dbo].[PagesToDelete]&amp;#39;&lt;/span&gt;) &lt;span class="kwrd"&gt;AND&lt;/span&gt; type &lt;span class="kwrd"&gt;in&lt;/span&gt; (N&lt;span class="str"&gt;&amp;#39;U&amp;#39;&lt;/span&gt;))&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:&lt;/span&gt; &lt;span class="kwrd"&gt;DROP&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; [dbo].[PagesToDelete]&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  17:&lt;/span&gt; &lt;span class="kwrd"&gt;IF&lt;/span&gt;  &lt;span class="kwrd"&gt;EXISTS&lt;/span&gt; (&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; * &lt;span class="kwrd"&gt;FROM&lt;/span&gt; sys.objects &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; object_id = OBJECT_ID(N&lt;span class="str"&gt;&amp;#39;[dbo].[aspnetUsersToDelete]&amp;#39;&lt;/span&gt;) &lt;span class="kwrd"&gt;AND&lt;/span&gt; type &lt;span class="kwrd"&gt;in&lt;/span&gt; (N&lt;span class="str"&gt;&amp;#39;U&amp;#39;&lt;/span&gt;))&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:&lt;/span&gt; &lt;span class="kwrd"&gt;DROP&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; [dbo].[AspnetUsersToDelete]&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  19:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:&lt;/span&gt; &lt;span class="kwrd"&gt;create&lt;/span&gt; &lt;span class="kwrd"&gt;table&lt;/span&gt; PagesToDelete (PageID &lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt; &lt;span class="kwrd"&gt;PRIMARY&lt;/span&gt; &lt;span class="kwrd"&gt;KEY&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  21:&lt;/span&gt; &lt;span class="kwrd"&gt;create&lt;/span&gt; &lt;span class="kwrd"&gt;table&lt;/span&gt; AspnetUsersToDelete (UserID uniqueidentifier &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt; &lt;span class="kwrd"&gt;PRIMARY&lt;/span&gt; &lt;span class="kwrd"&gt;KEY&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  23:&lt;/span&gt; &lt;span class="rem"&gt;-- Find out inactive anonymous users and store the UserID in the temporary&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  24:&lt;/span&gt; &lt;span class="rem"&gt;-- table&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  25:&lt;/span&gt; insert &lt;span class="kwrd"&gt;into&lt;/span&gt; AspnetUsersToDelete&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  26:&lt;/span&gt; &lt;span class="kwrd"&gt;select&lt;/span&gt; &lt;span class="kwrd"&gt;top&lt;/span&gt;(@NoOfUsersToDelete) UserID &lt;span class="kwrd"&gt;from&lt;/span&gt; aspnet_Users &lt;span class="kwrd"&gt;where&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  27:&lt;/span&gt; (isAnonymous = 1) &lt;span class="kwrd"&gt;and&lt;/span&gt; (LastActivityDate &amp;lt; (getDate()-@Days))&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  28:&lt;/span&gt; &lt;span class="kwrd"&gt;order&lt;/span&gt; &lt;span class="kwrd"&gt;by&lt;/span&gt; UserID &lt;span class="rem"&gt;-- Saves SQL Server from sorting in clustered index again&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  29:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  30:&lt;/span&gt; &lt;span class="kwrd"&gt;print&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;Users to delete: &amp;#39;&lt;/span&gt; + &lt;span class="kwrd"&gt;convert&lt;/span&gt;(&lt;span class="kwrd"&gt;varchar&lt;/span&gt;(255),@@&lt;span class="kwrd"&gt;ROWCOUNT&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  31:&lt;/span&gt; &lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  32:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  33:&lt;/span&gt; &lt;span class="rem"&gt;-- Get the pages of the users which will be deleted&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  34:&lt;/span&gt; insert &lt;span class="kwrd"&gt;into&lt;/span&gt; PagesToDelete &lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  35:&lt;/span&gt; &lt;span class="kwrd"&gt;select&lt;/span&gt; ID &lt;span class="kwrd"&gt;from&lt;/span&gt; Page &lt;span class="kwrd"&gt;where&lt;/span&gt; UserID &lt;span class="kwrd"&gt;in&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  36:&lt;/span&gt; (&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  37:&lt;/span&gt; &lt;span class="kwrd"&gt;select&lt;/span&gt; UserID &lt;span class="kwrd"&gt;from&lt;/span&gt; AspnetUsersToDelete&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  38:&lt;/span&gt; )&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  39:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  40:&lt;/span&gt; &lt;span class="kwrd"&gt;print&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;Pages to delete: &amp;#39;&lt;/span&gt; + &lt;span class="kwrd"&gt;convert&lt;/span&gt;(&lt;span class="kwrd"&gt;varchar&lt;/span&gt;(255),@@&lt;span class="kwrd"&gt;ROWCOUNT&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  41:&lt;/span&gt; &lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  42:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  43:&lt;/span&gt; &lt;span class="rem"&gt;-- Delete all Widget instances on the pages to be deleted&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  44:&lt;/span&gt; &lt;span class="kwrd"&gt;delete&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; WidgetInstance &lt;span class="kwrd"&gt;where&lt;/span&gt; PageID &lt;span class="kwrd"&gt;IN&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  45:&lt;/span&gt; ( &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; PageID &lt;span class="kwrd"&gt;FROM&lt;/span&gt; PagesToDelete )&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  46:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  47:&lt;/span&gt; &lt;span class="kwrd"&gt;print&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;Widget Instances deleted: &amp;#39;&lt;/span&gt; + &lt;span class="kwrd"&gt;convert&lt;/span&gt;(&lt;span class="kwrd"&gt;varchar&lt;/span&gt;(255), @@&lt;span class="kwrd"&gt;ROWCOUNT&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  48:&lt;/span&gt; &lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  49:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  50:&lt;/span&gt; &lt;span class="rem"&gt;-- Delete the pages&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  51:&lt;/span&gt; &lt;span class="kwrd"&gt;delete&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; Page &lt;span class="kwrd"&gt;where&lt;/span&gt; ID &lt;span class="kwrd"&gt;IN&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  52:&lt;/span&gt; ( &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; PageID &lt;span class="kwrd"&gt;FROM&lt;/span&gt; PagesToDelete )&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  53:&lt;/span&gt; &lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  54:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  55:&lt;/span&gt; &lt;span class="rem"&gt;-- Delete User Setting&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  56:&lt;/span&gt; &lt;span class="kwrd"&gt;delete&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; UserSetting &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; UserID &lt;span class="kwrd"&gt;IN&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  57:&lt;/span&gt; ( &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; UserID &lt;span class="kwrd"&gt;FROm&lt;/span&gt; AspnetUsersToDelete )&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  58:&lt;/span&gt; &lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  59:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  60:&lt;/span&gt; &lt;span class="rem"&gt;-- Delete profile of users&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  61:&lt;/span&gt; &lt;span class="kwrd"&gt;delete&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; aspnet_Profile &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; UserID &lt;span class="kwrd"&gt;IN&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  62:&lt;/span&gt; ( &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; UserID &lt;span class="kwrd"&gt;FROm&lt;/span&gt; AspnetUsersToDelete )&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  63:&lt;/span&gt; &lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  64:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  65:&lt;/span&gt; &lt;span class="rem"&gt;-- Delete from aspnet_UsersInRoles&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  66:&lt;/span&gt; &lt;span class="kwrd"&gt;delete&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; aspnet_UsersInRoles &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; UserID &lt;span class="kwrd"&gt;IN&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  67:&lt;/span&gt; ( &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; UserID &lt;span class="kwrd"&gt;FROm&lt;/span&gt; AspnetUsersToDelete )&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  68:&lt;/span&gt; &lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  69:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  70:&lt;/span&gt; &lt;span class="rem"&gt;-- Delete from aspnet_PersonalizationPerUser&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  71:&lt;/span&gt; &lt;span class="kwrd"&gt;delete&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; aspnet_PersonalizationPerUser &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; UserID &lt;span class="kwrd"&gt;IN&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  72:&lt;/span&gt; ( &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; UserID &lt;span class="kwrd"&gt;FROm&lt;/span&gt; AspnetUsersToDelete )&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  73:&lt;/span&gt; &lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  74:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  75:&lt;/span&gt; &lt;span class="rem"&gt;-- Delete the users&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  76:&lt;/span&gt; &lt;span class="kwrd"&gt;delete&lt;/span&gt; &lt;span class="kwrd"&gt;from&lt;/span&gt; aspnet_users &lt;span class="kwrd"&gt;where&lt;/span&gt; userID &lt;span class="kwrd"&gt;IN&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  77:&lt;/span&gt; ( &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; UserID &lt;span class="kwrd"&gt;FROm&lt;/span&gt; AspnetUsersToDelete )&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  78:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  79:&lt;/span&gt; &lt;span class="kwrd"&gt;PRINT&lt;/span&gt; &lt;span class="str"&gt;&amp;#39;Users deleted: &amp;#39;&lt;/span&gt; + &lt;span class="kwrd"&gt;convert&lt;/span&gt;(&lt;span class="kwrd"&gt;varchar&lt;/span&gt;(255), @@&lt;span class="kwrd"&gt;ROWCOUNT&lt;/span&gt;)&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  80:&lt;/span&gt; &lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  81:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  82:&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  83:&lt;/span&gt; &lt;span class="kwrd"&gt;drop&lt;/span&gt; &lt;span class="kwrd"&gt;table&lt;/span&gt; PagesToDelete&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  84:&lt;/span&gt; &lt;span class="kwrd"&gt;drop&lt;/span&gt; &lt;span class="kwrd"&gt;table&lt;/span&gt; AspnetUsersToDelete&lt;/pre&gt;&lt;/div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  85:&lt;/span&gt; &lt;span class="kwrd"&gt;GO&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;Now the question comes, when can I run this script? It depends on several factors:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The lowest traffic period. For example, USA midnight time when everyone in USA is sleeping if your majority users are from USA&lt;/li&gt;

&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The period when there’s no other maintenance tasks running like Index Defrag or Database Bakup. If by any chance any other maintenance task conflicts with this enormous delete operation, SQL Server is dead.&lt;/li&gt;

&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The operation will take from 10 mins to hours depending on the volume of trash to cleanup. So, consider the duration of running this script and plan other maintenance jobs accordingly.&lt;/li&gt;

&lt;li&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; It’s best to run 30 mins before INDEX DEFRAG jobs run. After the script completes, the tables will be heavily fragmented. So, you need to defrag the indexes.&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before running this script, there are some preparations to take: 
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure you have turned of AutoShrink from Database Property. Database size will reduce after the cleanup and if SQL Server tried to shrink the database, there will be a big IO activity. Turn off auto shrink because the database will grow again. &lt;/li&gt;

&lt;li&gt;Make sure the LOG file’s initial size is big enough to hold such enormous transactions. You can specify 1/3rd of the MDF size as LDF’s Initial Size. Also make sure the log file is not shrunk. Let it occupy HD space. It saves SQL Server from expanding the file and shrinking the file. Both of these require high Disk IO.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the cleanup job runs and the INDEX DEFRAG runs, the database performance will improve significantly. The tables are now smaller. That means the indexes are now smaller. SQL Server need not to run through large indexes anymore. Future INDEX DEFRAGs take shorter time because there’s not much data left to optimize. SQL Server also takes less RAM because it has to work with much less amount of data. Database backup size also reduces because the MDF size does not keep increasing indefinitely. As a result, the significant overhead of this cleanup operation is quite acceptable when compared to all the benefits. &lt;/p&gt;
Note: I will be posting some stuffs from my old blog to new blog. Please ignore if you have read them before. &lt;img src="http://msmvps.com/aggbug.aspx?PostID=709188" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net+sqlserver/default.aspx">asp.net sqlserver</category></item></channel></rss>