Monday, March 12, 2012

Large table cleanup with minimal locks

By Edward Polley, 2012/03/06

Problem

Your SQL Server production database must be available 7x24 but it contains millions of obsolete rows which hurt performance.  How do you delete these rows without the lock contention and business impact of a standard delete?  In this tip we look at how you can delete massive number of rows in small minimal lock batches.

Solution

Quick OLTP is critical to a business’s success so DBAs need to mindful of data contention caused by application cleanup jobs.  One approach is to select a huge number of keys in one pass then break the cleanup into small batches with commits and sleep windows to minimize contention.  I recommend enabling the cleanup in a SQL job and run at low system usage time.
This is accomplished with the T-SQL code below.  You would customize the definition of obsolete rows (I call deadheads) to your shop. In this case a sale without money and no contact is obsolete.  Historical cleanup is a common use of this routine.  This version works with multiple tables in this case a parent table and its two child tables.  The column SalesID relates the tables.
Two layers of temporary tables are used: the outer table to contain all the obsolete primary keys for this run; the inner table to contain a subset of the same.  The number of keys placed in the temporary tables is best determined by altering the number of rows until the highest rows deleted per minute is reached.  I started with 1,000 rows in the outer table and 100 in the inner table.  I slowly scaled up to 500,000 rows in the outer table and 5,000 rows in the inner table.  25,316 deletions per minute was the peak value.  Beyond 500,000 rows in the outer table the deletion per minute value declined on my server.
Since the application tables are defined with primary keys using the identity property the rows are inserted with ever increasing primary key values making it easy to pick up the oldest rows via SELECT top.  Your case may be based upon a date column so alter the SELECT top 500000 accordingly.
The code loops through the 500,000 row outer table loading 5,000 keys values into the inner table.  Those 5,000 rows are then deleted from the application tables and outer table. The last step is to truncating the inner table.  This loop continues until all 500,000 outer table rows are deleted.  I find keeping the inner table small (5000) minimizes lock contention but you will need to adjust this number to your shop.
If desired use the WAITFOR command to pause processing and allow other applications to process without contending with cleanup.
At any point the job can be cancelled resulting in a brief rollback only for the last inner table set of keys. Committed deletes are not rolled back.
The job can be restarted from the top without issue and can be run as many times a day as needed.  I run this job two times a night on tables needing a quick cleanup then pull back to once a week to maintain optimal performance.

The Code 

USE [msdb]
GO
/****** Object:  StoredProcedure [dbo].[usp_ObsoleteRowCleanup]    Script Date: 12/18/2011 14:00:38 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

/********************************************************************

  File Name:    usp_ ObsoleteRowCleanup.sql
  Applies to:   SQL Server 2005/8
  Purpose:      To cleanup obsolete rows.
  Prerequisite: None.
  Assumption:   Removal of obsolete rows improves performance
  Parameters:   None
  Returns:      0 = Succesful, 1 = Errors.
  Author:       Edward A. Polley
  Spec
  -- Definition of deadhead.
  Select COUNT(*) from SalesLead L, Transaction T
  WHERE L.SalesID = T.SalesID
  AND   L.ContactId IS NULL
  AND   T.MoneyIn = 0  

********************************************************************/
CREATE PROCEDURE [dbo].[usp_ ObsoleteRowCleanup]
--Will delete first 500000 deadheads
--Delete is from child tables: SalesZip and Transaction then parent SalesLead
-- 
AS

SET NOCOUNT ON
SET QUOTED_IDENTIFIER OFF

DECLARE
       @DeadHeadCnt int,     
       @Toprow int

BEGIN
      PRINT 'Building Outer Temp Tbl ' 
      PRINT getdate()
           
      CREATE TABLE #OuterTemp(SalesID bigint) -- hold all deadhead keys
      CREATE INDEX IX_OuterTemp_SalesId on #OuterTemp (SalesID) 
   
      CREATE TABLE #InnerTemp(SalesID bigint) -- hold subset of deadhead keys
      CREATE INDEX IX_InnerTemp_SalesID on #InnerTemp (SalesID)   

      INSERT INTO #OuterTemp                  -- select first 500,000 keys
        Select TOP 500000 L.SalesID from YourDB.dbo.SalesLead L (Nolock),
                                       YourDB.dbo.Transaction (Nolock) T
        WHERE L.SalesID = T.SalesID
        AND   L.LeadContactId IS NULL -–substitute your condition
        AND   T.MoneyIn = 0  
        OPTION (MAXDOP 8);          -- allow parallel processing                    
    -- mainline
      Select @DeadHeadCnt = count(*)From #OuterTemp
      PRINT 'Number of Dead Heads'
      PRINT @DeadHeadCnt

      While @DeadHeadCnt > 0
      BEGIN
            PRINT 'Begins deletes ' 
            PRINT getdate()
            PRINT 'Top row '
            SELECT @toprow = min(SalesID) From #OuterTemp   -- ever incr key
            PRINT @toprow
           
            BEGIN TRANSACTION
              INSERT INTO #InnerTemp      -- experiment with this value
                  Select TOP 5000 SalesID from #OuterTemp
            
  -- Delete from application tables by processing small intertemp
              DELETE from YourDB.dbo.SalesZIP where SalesID in
                  (Select SalesID from #InnerTemp (nolock) );  --innertemp
                 
              DELETE from YourDB.dbo.Transaction where SalesID in
                  (Select SalesID from #InnerTemp (nolock) ) ;
           
              DELETE from YourDB.dbo.SalesLead WHERE SalesID in
               (Select  SalesID from #InnerTemp (nolock) );

             --- Delete from outer table         
              DELETE from #OuterTemp WHERE SalesID in
               (Select  SalesID from #InnerTemp (nolock) )  ;

              Select @DeadHeadCnt = count(*)From #OuterTemp -- reset loop cnt
              TRUNCATE TABLE #InnerTemp   -- cleanup working table

              COMMIT 

            --WAITFOR DELAY '00:00:01'   -- adjust as needed
        
            PRINT 'End Deletes' 
      END  
-- Destroy all temporary tables.
IF OBJECT_ID('tempdb..#OuterTemp') IS NOT NULL
      DROP TABLE #OuterTemp

IF OBJECT_ID('tempdb..#INNERTEMP') IS NOT NULL
      DROP TABLE #InnerTemp
END
GO

 

Sunday, March 11, 2012

Duqu Trojan contains mystery programming language in Payload DLL

March 9, 2012, 4:00 PM EST
Experts at Russian computer security company Kaspersky have come to the conclusion that parts of the Duqu Trojan are written in an unknown programming language. Much of the code is identified as standard C++ but the team is clueless as to the origin of other segments and is asking the programming community for assistance.
Duqu borrows heavily from another high-profile security threat, Stuxnet, with some even referring to it as Stuxnet 2.0. The code in question is part of the Payload DLL, a section of the trojan that sends and receives instructions from an outside source once it has infiltrated a system. It is object-oriented but otherwise unlike anything the team at Kaspersky has seen before.
Experts have dubbed this portion of code the Duqu Framework and based on the sheer complexity of the instructions, it’s believed that the trojan is funded by a wealthy organization or a national effort.
“With the extremely high level of customization and exclusivity that the programming language was created with, it is also possible that it was made not only to prevent external parties from understanding the cyber-espionage operation and the interactions with the C&Cs, but also to keep it separate from other internal Duqu teams who were responsible for writing the additional parts of the malicious program,” said Alexander Gostev, chief security expert at Kaspersky.
Igor Soumenkov from Kaspersky has authored a blog post detailing information on the Duqu Framework and asking those in the programming community to help identify the mystery code. This is what the team has concluded thus far.
  • The Duqu Framework appears to have been written in an unknown programming language.
  • Unlike the rest of the Duqu body, it's not C++ and it's not compiled with Microsoft's Visual C++ 2008.
  • The highly event driven architecture points to code which was designed to be used in pretty much any kind of conditions, including asynchronous commutations.
  • Given the size of the Duqu project, it is possible that another team was responsible for the framework than the team which created the drivers and wrote the system infection and exploits.
  • The mysterious programming language is definitively NOT C++, Objective C, Java, Python, Ada, Lua and many other languages we have checked.
  • Compared to Stuxnet (entirely written in MSVC++), this is one of the defining particularities of the Duqu framework.
Those with any insight are encouraged to submit a comment on the blog post.

Monday, March 5, 2012

Change the port number for connections to SQL Server

By Dan Hess, 2012/03/01 

By default, SQL Server will use port 1433 for incoming communication. A named instance, by default, uses a dynamic port that it chooses from a list of available ports. 
Some reasons to change the listening port:
1) As the default port 1433 could be targeted by attacks it could be changed to limit exposure.  (This is a weak form of security and should not be used as a sole means of protection)
2) For named instances the port can be specifically defined to allow for disabling of the SQL Server browser service. 
3) For named instances, a specifically defined port enables firewalls to be placed around the SQL Server server.
Note: discussion of the above points is beyond the scope of this article

SQL Server Configuration Manager

We'll use the 'SQL Server Configuration Manager' to assign a specific port to our instance. Open it and expand the 'SQL Server Network Configuration' node, then single click 'Protocols for MSSQLSERVER' (if you're changing the port for a named instance, the node will be 'Protocols for '). This will populate the right hand navigation pane; right click 'TCP/IP' and choose 'Properties'. The screenshot shows the navigation, as well as the difference between a default and named instance:



In the pop-up, choose the 'IP Addresses' tab. There will be a list of various adapters ranging from 'IP1' to 'IPAll'; for each adapter remove any zeros (0) from the 'TCP Dynamic Ports' dialog box (a zero in that box indicates that the database engine is listening on a dynamic port). In the 'TCP Port' dialog box, type the port number that you would like the engine to use to accept connections. In the screenshot, I've designated port 2866 as my listening port:

 
Note: make sure to modify all adapters 'IP1' through 'IPAll'

Click 'OK' to close the popup and implement the changes. 
For the changes to take effect, the SQL Server service needs to be restarted. In the left hand navigation pane, single click 'SQL Server Services'. This populates the right hand navigation pane with the services list.  Find the service responsible for the instance that you just changed, right click and choose 'Restart'. The screenshot shows this process, as well as the difference between the default instance and named instance service:

 

Conclusion

This process should be quite straight forward, although there are a few potential pitfalls:
  • Make sure that the port that gets assigned to the SQL Server engine is not already in use.
  • If the SQL Server Browser service is not running, connection strings will have to specify the port number in order to connect.
  • Host based firewall rules may need to be modified to allow connections into the newly specified port.

 source: http://www.sqlservercentral.com/articles/Port/75740/

Find which port SQL Server is using to establish connections

By Dan Hess, 2011/09/08

By default, SQL Server listens on port 1433 for TCP/IP connections and 1434 for UDP broadcasts. But what if this was changed and what about a named instance? You can find the listener port in a few ways:
  1. Check the Windows Application event log - Event ID 26022
  2. Use SQL Server Configuration Manager
  3. Query the Windows Registry

Windows application event log

Each time an instance starts, SQL Server will record its listening port(s) in the Windows Event Viewer. To find this, open up the Windows Event Viewer and choose the 'Application' event log. If you filter on Event ID 26022, you should see four events associated with the start up. Look for the event that has this in the message body:



I've shown here that the named instance 'JOHNSQLSERVER' is listening on port 49526. As I stated, there are four events associated with the start up; the other three events will report the IPv6 protocol and the UDP broadcast port:
Server is listening on [ 127.0.0.1 49527].
Server is listening on [ ::1 49527].
Server is listening on [ 'any' 49526].
Make sure to look for the message in the image. The same information also apples for the default instance.

SQL Server Configuration Manager

Another easy and effective way is to use SQL Server Configuration Manager. Open it up and expand 'SQL Server Network Configuration' in the left hand pane. You'll see menu items for protocols for your various instances. Single click one of the protocol menu items and you'll get a list of protocols for that instance appearing in the right hand pane. Right click 'TCP/IP' and choose 'Properties':



Choose the 'IP Addresses' tab. Scroll to the bottom of the list and find the 'IPAll' section. The 'TCP Port' setting will have the listening port, unless the instance is set up to listen dynamically. If so, the 'TCP Dynamic Ports' setting will contain the listening port:


Using the Windows Registry (via TSQL)

The registry also stores this information. It can be read using the following:
DECLARE @InstName VARCHAR(16)

DECLARE @RegLoc VARCHAR(100)

SELECT @InstName = @@SERVICENAME

IF @InstName = 'MSSQLSERVER'
  BEGIN
    SET @RegLoc='Software\Microsoft\MSSQLServer\MSSQLServer\SuperSocketNetLib\Tcp\'
  END
 ELSE
  BEGIN
   SET @RegLoc='Software\Microsoft\Microsoft SQL Server\' + @InstName + '\MSSQLServer\SuperSocketNetLib\Tcp\'
  END

EXEC [master].[dbo].[xp_regread] 'HKEY_LOCAL_MACHINE', @RegLoc, 'tcpPort'
This returns the port(s) in a result set as shown here:



Conclusion

There are multiple ways to determine the port on which a SQL Server instance is listening. If you have trouble connecting, use one of the techniques outlined here to confirm that you're connecting to the correct port.

source: http://www.sqlservercentral.com/articles/networking/73238/

Sweating Makes You Smart!!!

Does Walking Make You Smart? Yes, and In More Ways Than You Think: Walking is a win-win for psychological, cognitive, and physical health
Published on February 28, 2012 by Thomas G. Plante, Ph.D., ABPP in Do the Right Thing


Research suggests that walking may not make you a genius but it will improve your attention and concentration not to mention help your mood, well being, self-esteem, and even your physical health. So, your most important accessory when getting dressed in the morning may very well be your pedometer!
Regular physical exercise such as walking has been demonstrated to help improve both mental and physical health. Certainly the many physical health benefits of regular exercise are well known and researched. Improvements in cardiovascular functioning, weight loss, metabolism, and so forth can be expected with ongoing regular exercise. Psychological and mental health benefits are well known too. Research consistently has found that regular exercise lowers anxiety, depression, and stress and improves well-being and self-esteem. Additionally, cognitive benefits including improved attention, concentration, and problem solving can be found among exercisers too.


Yet, even with all these wonderful benefits of regular exercise the vast majority of Americans don't meet even minimal recommended amounts of exercise. There are a variety of reasons for this lack of exercise behavior among the population including time pressures and lack of commitment to do so. This is one reason why walking is such an important exercise for most people.

Many may not take the time, energy, and money to join a health club or gym or perhaps participate in exercise activities that are harder to accomplish such as swimming, tennis, racket ball, biking, and the like. Many sports are skill based, prone to injury, and cost a lot of money to do (e.g. sailing, golf, polo). Walking is perfect since you can do it anywhere and at any time and it is free with no special skill or expensive equipment needed. Just a decent pair of walking shoes and you are good to go. Most of us can and do walk and must find a way to make that happen at levels that provide us with the many mental and physical health benefits associated with exercise.
 

One helpful way to improve walking behavior is to always (and I do mean always) wear a pedometer (ok...not in the shower or in bed). They provide ongoing feedback on your walking progress and most professionals suggest aiming for 10,000 steps per day. This translates into about 5 miles of walking. A pedometer is a great motivator since it gives you a fairly accurate description of your exercise activity. Don't go to bed unless you have 10,000 steps or more is the needed daily battle cry. Once you buy into the 10,000 steps program idea then you will hopefully manage your day in a way to get steps. Walks may be long or short but as long as you keep your body moving you'll accumulate steps. Next thing you know you'll walk around the block before a scheduled meeting if you arrive early or you'll park further away from your destination to get some steps. Maybe you'll suggest taking a walk with a friend or colleague rather than sitting while talking. Perhaps you'll walk all over an airport terminal rather than sitting waiting for a flight. Maybe you'll be so pleased with your progress that you'll want to get more than 10,000 steps a day and enjoy getting more and more steps.

Since the mid 1970's I have ran every day for about a half hour. That buys me about 5,000 steps each morning. Walking around during the day usually gets me another 5,000 steps and then my wife and I typically take a walk with our dog at the end of the day getting another few thousand steps. My wife and I find ourselves being highly attentive to the step counter (actually she thinks I'm a bit obsessive about it) and often rather than say, "let's take a walk", we'll say, "let go get some steps!"
While accumulating steps you'll likely notice that your thinking is clearer, you are more attentive, happier, and you'll lose some weight and feel more toned. It is all a win-win.

So, does walking make you smarter? You betcha and in many more ways than you might think.