Category: Performance Tuning

  • Spinlocks lightweight synchronization primitives

    Spinlocks are lightweight synchronization primitives which are used to protect access to data structures. Spinlocks are used to access data structures for a very short period of time. When a thread attempting to acquire a spinlock and if it is unable to obtain access it executes in a loop periodically checking to determine if the resource is available instead of immediately yielding.

    After some period of time a thread waiting on a spinlock will yield before it is able to acquire the resource in order to allow other threads running on the same CPU to execute. This is known as a backoff.

    When a large number of threads are contending for access to a single spinlock and it can lead to performance problems

    You can use below DMV to get the SPIN LOCK information

    select * from sys.dm_os_spinlock_stats

    Examples
    FGCP_PRP_FILL
    OPT_IDX_STATS
    BUF_FREE_LIST

  • Best Practices SQL Server Transaction Log

    Background
    In SQL Server Database Recovery model will decide how the transaction log will be logged in transaction log file. Transaction log file extension is .LDF

    Full – Transaction log is fully logged (Can take log backup)
    Bulk Logged – Bulk transaction is minimally logged (Can take log backup)
    Simple – Transaction log will be truncated on checkpoint

    In transaction log file transactions are sequentially logged, every record in transaction log file is uniquely identified by log sequence number (LSN). LSN data type is Numeric (25,0)

    You can follow below best practices for the transaction log file

    1. Don’t create multiple log files : As transactions will be logged into log file sequential manner it would not help for data stripping across multiple files
    2. Keep the transaction log file on the separate drive
    3. Identify the RPO and RTO for the database and according to that choose the recovery model and correct log backup strategy
    4. RAID 1 + 0 is high recommended for transaction log
    5. AUTO SHRINK should be always off on the database
    6. Pre-allocate the space to transaction log file, it will improve the performance. Don’t depend on the auto growth option.
    7. Always set the values of Initial size, max size and growth property of the transaction log file
    8. Always set auto growth value, don’t set in percentage
    9. Transaction Log file internal fragmentation can also lead the performance and database recovery issue. Database should not have an excessive number of Virtual Log Files (VLFs) inside the Transaction Log. Having a large number of small VLFs can slow down the recovery process that a database goes through on startup or after restoring a backup. Make sure transaction log initial size and log growth defined well to avoid internal fragmentation
    10. External fragmentation can be removed by using disk defragmentation utility
    11. In case of Transaction log full, please use below query to check the cause of the log full and take the decision accordingly.

    SELECT name ,
    recovery_model_desc ,
    log_reuse_wait_desc
    FROM sys.databases
    WHERE name = @DatabaseName

  • Table Hints – NoLock vs ReadPast

    When any data in a database is read or modified, the database engine uses special type of mechanism, called locks, to maintain integrity in the database. Locks will be used to make sure the transaction consistency.

    NoLock Table Hint
    – Will allow you to read the uncommited data
    – Only used with SELECT statement
    – Blocking will not occur
    – Will reduce the concurrency and improve the performance at some extent
    – Risk of doing Phantom reads

    Let’s create table for the NOLOCK and READPAST hint demo

    create table tranDemo
    (
    			id int identity(1,1),
    			name varchar(10)
    )
    
    insert into tranDemo values ('Jugal')
    insert into tranDemo values ('Nehal')
    

    –Now let’s update the values by specifying the explicit transaction and don’t commit/rollback the transaction

    begin transaction
       update tranDemo
       set name = 'DJ'
       where name = 'Jugal'
    

    Now open new query window and execute the below query and you will notice query will not return data and will continue running as it is blocked

    select * from trandemo
    

    Now open new query window and execute the below query to check the blocking, you can see the blocking SPID in the result set

    sp_who2 active
    

    Now open new query window and execute the below query using NOLOCK hint and it will return data, yet transaction is not committed but it will return the updated value.

    select * from trandemo(NOLOCK)
    

    READPast Table Hint: Less commonly used table hint than NOLOCK. This hint specifies that the database engine not consider any locked rows or data pages when returning results.
    – Will only read the commited rows which are not locked
    – Blocking will not occur
    – Only used with SELECT statement
    – Will reduce the concurrency and improve the performance at some extent
    – Result set returned by this hint is not perfect as it will not retun the locked rows or pages, so you can not make any decision based on data

    Now open new query window and run the below query it will return only one record (“Nehal”) which is not locked or modified

    select * from trandemo(ReadPast)
    
  • Script to find out Stored Procedures which are Using most resources

    While doing the stored procedure performance tuning, you can use sys.dm_exec_procedure_stats DMV to get resource intensive procedures.

    You can use the below script for it.

    SELECT DB_NAME(database_id) AS DatabaseName
          ,OBJECT_SCHEMA_NAME(object_id,database_id) AS [SCHEMA_NAME] 
          ,OBJECT_NAME(object_id,database_id)AS [OBJECT_NAME]
          ,cached_time
          ,last_execution_time
          ,execution_count
          ,total_worker_time / execution_count AS Average_CPU
          ,total_elapsed_time / execution_count AS Average_Elapsed_Time
          ,total_logical_reads / execution_count AS Average_Logical_Reads
          ,total_logical_writes / execution_count AS Average_Logical_Writes
          ,total_physical_reads  / execution_count AS Average_Physical_Reads
    FROM sys.dm_exec_procedure_stats 
    where database_id <> 32767
    ORDER BY Average_Logical_Reads DESC
    
  • Script to check the database Properties

    It is always good to have the idea about the database properties while doing the migration, performance tuning or configuration.

    You can execute the below script to get the database property information.

    select 
     sysDB.database_id,
     sysDB.Name as 'Database Name',
     syslogin.Name as 'DB Owner',
     sysDB.state_desc,
     sysDB.recovery_model_desc,
     sysDB.collation_name, 
     sysDB.user_access_desc,
     sysDB.compatibility_level, 
     sysDB.is_read_only,
     sysDB.is_auto_close_on,
     sysDB.is_auto_shrink_on,
     sysDB.is_auto_create_stats_on,
     sysDB.is_auto_update_stats_on,
     sysDB.is_fulltext_enabled,
     sysDB.is_trustworthy_on
    from sys.databases sysDB
    INNER JOIN sys.syslogins syslogin ON sysDB.owner_sid = syslogin.sid