Yet another SQL Server enthusiast

2013-10-04

Finding Scans

Filed under: index,scan,sql server 2008 r2 — ---- @ 8:19 AM

Starting with SQL Server 2005, the execution plans are stored as XML. Combining this fact with powerful XQueries the result is endless (well, almost) possibilities. For example, somebody could write a simple SELECT statement to find out all execution plans including [ [ Clustered] Index | Table ] Scan operators.

Step #1 Run this script to create a stored procedure:

Code Snippet
USE AdventureWorks2008R2;
GO
CREATE PROCEDURE Sales.spTest
AS
SELECT  soh.SalesOrderID
FROM    Sales.SalesOrderHeader soh
WHERE   soh.ShipDate>='20070101';
GO

Step #2 Execute the newly created stored procedure (EXEC Sales.spTest) using Actual Execution Plan option activated (see here how). The result will be the following execution plan:

XmlExecutionPlan

Step #3: Now, run the following SELECT statement to find out all execution plans which include an [ [ Clustered] Index | Table ] Scan operator:

Code Snippet
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
WITH XMLNAMESPACES
(
    DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan'
)
SELECT    TOP(10)
        crt_db.[dbid],
        DB_NAME(crt_db.[dbid]) AS database_name,
        pl.objectid,
        QUOTENAME(OBJECT_SCHEMA_NAME(pl.objectid, crt_db.[dbid]))+'.'+QUOTENAME(OBJECT_NAME(pl.objectid, crt_db.[dbid])) AS object_name,
        pl.query_plan,
        src.text AS source_code,
        pl.query_plan.exist('//RelOp[@PhysicalOp="Clustered Index Scan"]') AS [Has Clustered Index Scan],
        pl.query_plan.exist('//RelOp[@PhysicalOp="Index Scan"]') AS [Has Index Scan],
        pl.query_plan.exist('//RelOp[@PhysicalOp="Table Scan"]') AS [Has Table Scan],
        cp.size_in_bytes,
        cp.usecounts
FROM    sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) pl
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) src
CROSS APPLY (
    SELECT    CONVERT(INT, plat.value) AS [dbid]
    FROM    sys.dm_exec_plan_attributes(cp.plan_handle) plat
    WHERE    plat.attribute = 'dbid'
) crt_db
WHERE   pl.query_plan.exist('//RelOp[
    @PhysicalOp = "Clustered Index Scan"
    or @PhysicalOp = "Index Scan"
    or @PhysicalOp = "Table Scan"
]')=1
ORDER BY cp.usecounts DESC;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

Results:

QueryCache

Revision History

2013-10-07 Update #1 (Changes: step 2 and 3)

About these ads

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Rubric Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: