Help: SQL Server

Sharing my knowlege about SQL Server Troubleshooting Skills

  • Blog Stats

    • 2,039,819 hits
  • Select GETDATE()

    January 2014
    M T W T F S S
     12345
    6789101112
    13141516171819
    20212223242526
    2728293031  

Archive for January, 2014

A-Z of In-Memory OLTP : Usage of sys.dm_exec_query_stats and sys.dm_exec_procedure_stats

Posted by blakhani on January 23, 2014


Have you ever played any game where crime has occurred in past and you need to look at evidences to find out who was criminal? Any post-mortem needs data collected during past. In SQL Server world DBAs are detectives where they sometime needs post-mortem about performance issue reported on server. To equip them SQL Server provides the statistics about the query and being is constantly gathered once they are executed. As long as plan is there is cache, we can use stats DMVs (sys.dm_exec_query_stats and sys.dm_exec_procedure_stats) to find the time taken by query and resources taken in the past. If you try to find query to find Top 10 CPU / IO consumers in the past, you will easily get query.

There is a little difference in this behavior when it comes to In-Memory OLTP. The gathering of execution stats collection is off by default. Here is the quick repro about what I mean. I have created two procedures to do same task.

One is interoperable.

Create Procedure [dbo].[SelectName_traditional]
@iID int

as Select vFName,vLName from dbo.MyFirstMemporyOptimizedTable
  where iID = @iID
GO

and another is natively compiled

CREATE PROCEDURE [dbo].[SelectName_Native] @iID INT
  WITH 
    NATIVE_COMPILATION,  SCHEMABINDING,  EXECUTE AS OWNER
AS 
BEGIN ATOMIC 
  WITH 
(TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = 'us_english')  Select vFName,vLName from dbo.MyFirstMemporyOptimizedTable
  where iID = @iID

END

 

Let’s execute both stored procedure 10 times using below code

exec SelectName_traditional 1
go 10
exec SelectName_Native 1
go 10

 

If I look at stats DMV, I would see information only for “SelectName_traditional” procedure as below. Here is the query for query_stats DMV

SELECT 
QT.TEXT AS STATEMENT_TEXT,
QP.QUERY_PLAN,
QS.TOTAL_WORKER_TIME AS CPU_TIME
FROM SYS.DM_EXEC_QUERY_STATS QS
CROSS APPLY SYS.DM_EXEC_SQL_TEXT (QS.SQL_HANDLE) AS QT
CROSS APPLY SYS.DM_EXEC_QUERY_PLAN (QS.PLAN_HANDLE) AS QP
where QT.TEXT like '%MyFirstMemporyOptimizedTable%'

 

image

Here is the query for procedure_stats DMV

select object_id,
object_name(object_id) as 'object name',
cached_time,last_execution_time,
execution_count,total_worker_time,
last_worker_time,min_worker_time,
max_worker_time,total_elapsed_time,
last_elapsed_time,min_elapsed_time,
max_elapsed_time 
from sys.dm_exec_procedure_stats
where database_id=db_id('SQLSeverHelp_IMO') 

image

As we can see above that there is no entry for SelectName_Native.

Above confirms that, by default collection is off as its recommended to turn on stats collection only for a limited amount of time as needed for troubleshooting. This is done to minimize the performance impact on the production workload due to stats collection. We can turn on (and turn off as well) the collection of statistics by running below “control” procedures. One procedure is for collection at query level (within natively complied procedure) and other is at procedure level.

sys.sp_xtp_control_query_exec_stats: Here is the tooltip shown in SSMS.

image


sys.sp_xtp_control_proc_exec_stats:Here is the tooltip shown in SSMS.

image

As you would notice via tool tip that “query” stats can be turned on for a specific database id and object id, which gives us granular control of data collection. Once they are turned on, we can see the entry in statistics DMVs.

image

I have done DBCC FREEPROCCACHE and ran the same batch again to execute both procedure 10 times. Here is the result of earlier query for procedure stats DMV.

image

Now we can see two rows. Notice Zero values in various columns. Let’s do the same for query level.

image 

and look at query stats DMV now..

image

Now, we can see new row for natively complied procedure as well.

Few important notes, based on my learning on CTP2.

  1. the changes done via control procedures are reverted back to OFF after restart.
  2. DBCC FREEPROCCACHE doesn’t impact the entry shown for natively complied procedures in stats DMV as they are not in procedure cache.
  3. CPU, IO column value would be zero for natively compiled procedures.
  4. Turning off the control procedures doesn’t remove the value. Only way to remove them is either drop and recreate the procedure or restart.

Hope you have learned something new today.

  • Cheers,
  • Balmukund Lakhani
  • Twitter @blakhani
  • Author: SQL Server 2012 AlwaysOnPaperback, Kindle
  • Advertisement

    Posted in A - Z Series, In Memory OLTP, In-Memory OLTP, SQL Server 2014 | Tagged: , , , , , , , , , , , , , , , , , | 5 Comments »

    A-Z of In-Memory OLTP : What’s new in Execution Plan

    Posted by blakhani on January 21, 2014


    I still remember the day when I was interviewed for my job with Microsoft. It was kind of a discussion about SQL Sever internals rather than interview. Of course, we had discussion about SQL Server Performance Tuning as well. Interviewer asked – “If there is a query taking very long time to execute, what would you do?” I tried few answers like blocking, resource bottleneck and also said that we can look at the execution plan. I was aware of few bad operators in execution plan and I explained those. Anyways, after 2 hours of discussion, the interviewer was satisfied that I know SQL Server features. I also got feedback that more than current knowledge, I have passion to learn, help someone and share my knowledge. End result – I was hired! After joining Microsoft SQL Support team, I am learning since day 1 and learning and sharing never stopped for me. Performance tuning has been my favorite and I would still love to see execution plans to learn more about query execution.

    In this blog of A-Z of In-Memory OLTP Series, we would talk about execution plan related changes with respect to In-Memory OLTP.

    Limitation on Natively Compiled Stored Procedure

    If we try to get execution plan of any natively complied stored procedure via SSMS using “Include Actual Execution Plan” and executing it; it won’t work. There is no plan in procedure cache for natively compiled stored procedures. Even if we try set statistics profile on, it won’t work.

    image

    Only way to get query plan for natively compiled procedure is to get estimated plan. That can be done using TSQL “set showplan_xml on” statement or via SSMS “Display Estimated Execution Plan”. This restriction is not applicable for TSQL statements touching in-memory tables and we can get actual plan as well.

    How to Identify which In-Memory Index is being used?

    We have earlier created table called MyFirstMemporyOptimizedTable with Primary Key (with hash index) and another Hash Index. There is another type of non-clustered index in-memory world called range index, which we would cover later in the series. We would create MySecondMemporyOptimizedTable with range index and I’ve highlighted below.

    CREATE TABLE [dbo].[MyFirstMemporyOptimizedTable]
    (
        [iID] [int] NOT NULL,
        [vFName] [varchar](20) COLLATE Latin1_General_100_BIN2 NOT NULL,
        [vLName] [varchar](20) COLLATE Latin1_General_100_BIN2 NOT NULL
    
    INDEX [imo_idx_vFname] NONCLUSTERED HASH 
    (
        [vFName]
    )WITH ( BUCKET_COUNT = 1048576),
    CONSTRAINT [imo_pk_iID] PRIMARY KEY NONCLUSTERED HASH 
    (
        [iID]
    )WITH ( BUCKET_COUNT = 1048576)
    )WITH ( MEMORY_OPTIMIZED = ON , DURABILITY = SCHEMA_AND_DATA )
    
    GO
    
    CREATE TABLE [dbo].[MySecondMemporyOptimizedTable]
    (
        [iID] [int] NOT NULL,
        [vFName] [varchar](20) COLLATE Latin1_General_100_BIN2 NOT NULL,
        [vLName] [varchar](20) COLLATE Latin1_General_100_BIN2 NOT NULL
    
    INDEX [imo2_idx_vFname] NONCLUSTERED  
    (
        [vFName]
    ),
    CONSTRAINT [imo2_pk_iID] PRIMARY KEY NONCLUSTERED HASH 
    (
        [iID]
    )WITH ( BUCKET_COUNT = 1048576)
    )WITH ( MEMORY_OPTIMIZED = ON , DURABILITY = SCHEMA_AND_DATA )
    
    

    Hash Index

    Below query is going to use Hash index

    select count(*) 
    from MyFirstMemporyOptimizedTable
    where iID = 0

     

    And we would see Index Seen with “NonClusteredHash” keyword, which denoted hash index being used.

    image

    If we look at “storage” for the “Index Seek” operator, it would be “MemoryOptimized”

    image

    Range Index

    Here is a query for Range Index for second table

    select count(*) 
    from MySecondMemporyOptimizedTable
    where vFName= 'Balmukund'
    

     

    image

    Estimated I/O Cost is zero

    We can also notice that Estimated I/O Cost is zero. Of course it would be zero as table is residing in memory.

    image

    NoParallelForMemoryOptimizedTables is a reason for non-parallelized plan

    While looking at XML plan of the query, I noticed something new and I have drawn a box.

    image

    NonParallelPlanReason="NoParallelForMemoryOptimizedTables" This would mean that in-memory table operations would not go for parallelism.

    Hope you have learned something new today.

  • Cheers,
  • Balmukund Lakhani
  • Twitter @blakhani
  • Author: SQL Server 2012 AlwaysOnPaperback, Kindle
  • Posted in A - Z Series, In Memory OLTP, In-Memory OLTP, SQL Server 2014 | Tagged: , , , , , , , , , , , , , , , | 2 Comments »

    A-Z of In-Memory OLTP : Monitoring Memory Usage

    Posted by blakhani on January 16, 2014


    Monitoring is a human nature to be safe and avoid and unexpected failure. Whenever we drive a car at high speed, its human nature to have a look at speedometer. Whenever you go to visit doctor, he would do some monitoring of certain parameters and then ask relevant question to troubleshoot the problem which you tell him. (Oh God! Troubleshooting has become part of my examples, even for doctor!)

    In SQL Server, how do you normally monitor space used by a table? Generally we use sp_spaceused and provide table name which gives good amount of details. But interestingly enough, the store procedure would NOT work for in-memory tables as shown below.

    select count(*) as 'count' 
    from [dbo].[MyFirstMemporyOptimizedTable]
    go
    sp_spaceused 'MyFirstMemporyOptimizedTable'
    go
    

     

    image

    Our table MyFirstMemporyOptimizedTable has good amount of rows and can’t be using zero space as reported by sp_spaceused. In order to get the memory used by in-memory tables, we need to use another DMV called dm_db_xtp_table_memory_stats. Now, how do I write a query? I generally look for the UI interface or standard report which gives me the data and then use profiler to find the nicely formatted query.

    I was able to find a standard report for memory usage of in-memory tables called “Memory Usage By Memory Optimized Objects” as shown below.

    image

    I launched the report and captured profiler to get the query. Here is the query which can get us the data for all IMO tables in the database. (captured by profiler, not written by me)

     SELECT t.object_id
        ,t.NAME
        ,ISNULL((
                SELECT CONVERT(DECIMAL(18, 2), (TMS.memory_used_by_table_kb) / 1024.00)
                ), 0.00) AS table_used_memory_in_mb
        ,ISNULL((
                SELECT CONVERT(DECIMAL(18, 2), (TMS.memory_allocated_for_table_kb - TMS.memory_used_by_table_kb) / 1024.00)
                ), 0.00) AS table_unused_memory_in_mb
        ,ISNULL((
                SELECT CONVERT(DECIMAL(18, 2), (TMS.memory_used_by_indexes_kb) / 1024.00)
                ), 0.00) AS index_used_memory_in_mb
        ,ISNULL((
                SELECT CONVERT(DECIMAL(18, 2), (TMS.memory_allocated_for_indexes_kb - TMS.memory_used_by_indexes_kb) / 1024.00)
                ), 0.00) AS index_unused_memory_in_mb
    FROM sys.tables t
    INNER JOIN sys.dm_db_xtp_table_memory_stats TMS ON (t.object_id = TMS.object_id)

    Here is the output:

    image

    If we look at report, we would get exactly same output but in more “presentable” format as below.

    image

    If we look at the bottom area of report, it’s the output of earlier query.

    If you find other ways to monitor the memory usage, write it in comment section and share with the world.

  • Cheers,
  • Balmukund Lakhani
  • Twitter @blakhani
  • Author: SQL Server 2012 AlwaysOnPaperback, Kindle
  • Posted in A - Z Series, Hekaton Series, In Memory OLTP, In-Memory OLTP | Tagged: , , , , , , , , , , , , , , , , | 1 Comment »