Viewing the Plan Cache

I’m working on a script and wanted to know how SQL was caching the query plan. So I wrote this little snippet. The only real value I’m adding here is getting the XQuery correct to pull out the SQL itself.

-- Run your query here
        qp.query_plan.value(N'(//@StatementText)[1]', N'NVARCHAR(MAX)')
    FROM sys.dm_exec_cached_plans AS cp
        CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp;

Of course, I don’t recommend that DBCC in a production environment. But in a dev environment, it makes things easy.

Pages Used

One of the items in my toolbox is this simple query that returns the number of pages used by different tables in the database. The nice thing is that it gives one simple number that includes indexes, lob data – basically the whole table.

  FROM sys.dm_db_partition_stats AS ddps
    INNER JOIN sys.objects AS o
      ON ddps.object_id = o.object_id
    INNER JOIN sys.schemas AS s
      ON o.schema_id = s.schema_id
  ORDER BY SUM(ddps.used_page_count) DESC;

I just used this on a database today to find that there are some leftover tables from a migration a while back that are eating up a considerable amount of space. Time to run some DROP TABLE scripts!

/* Why didn’t I think of this years ago? /*

So, I attended the PASS Summit last week in Seattle. If you’ve never been, I highly recommend it. Especially if it’s in Seattle. Yes, the character of the town is basically dark, rainy, and uphill both ways. But the coffee is good, the seafood is better (especially for a midwesterner like me), and the place is just simply one of the nicer downtowns I’ve seen.

But the PASS Summit itself is also worth it, Seattle or not. You pick up a lot of great stuff, much of it at a very deep level. Adam Machanic’s pre-con on Tuesday, for instance, was such a deep dive into parallelism that my eyes were glazed over by the end of it.

And then there are the little things. The stuff that make you want to kick yourself for not thinking of it before.

I write a lot of dynamic SQL. I have tons of stored procedures that include this little gem:


And then hundreds of lines of conditionals and string concatenation and parameter substitution, followed by sp_executesql.

But what had never occurred to me was this:

DECLARE @stmt NVARCHAR(MAX) = N'/* dbo.NameOfCallingStoredProcedure */ ';


And now when it’s six months later, and I get a call from a DBA who’s trying to troubleshoot a query plan that’s gone sideways, and neither of us know or remember what’s actually generating that query.

It’s the little things, sometimes, that make the big difference.

By the way, this came from Jeremiah Peschka’s AD-302 session, Dynamic SQL: Build Fast, Flexible Queries.