I downloaded the SQL Server First Aid Kit from Brent Ozar's website. When I tried to run the sp_BlitzIndex script against my master database via Microsoft Sql Server Management Studio while logged in as the Azure database server level admin and I got the following error:

Msg 262, Level 14, State 18, Procedure sp_BlitzIndex, Line 18 CREATE PROCEDURE permission denied in database 'master'.

I successfully created the procedure on the database instance I wanted to test. When I executed the procedure I got an error stating:

Msg 50000, Level 16, State 1, Line 1265 Invalid object name 'mydatabase.sys.partitions'.

Next I tried to be clever and run the stored procedure code directly against the master database without creating the stored procedure and got the following error:

Msg 50000, Level 15, State 1, Line 1267 Reference to database and/or server name in 'mydatabase.sys.indexes' is not supported in this version of SQL Server.

I don't feel confident enough to start toying with the inner workings of ~2700 lines of index heuristic logic. Is there a quick, and easy way to get this stored procedure to work nicely on Azure SQL Database or should I look elsewhere for an index analyzing tool/stored procedure?


2 Answers 2


Kendra here (the author of sp_BlitzIndex)

First, thanks for being interested in the procedure and trying it out.

Azure doesn't expose all the dynamic management views that we get in the boxed product. I do actually reference sys.dm_db_partition_stats, but there's other info I need to get from sys.partitions for other users. (Is it using compression? What type?)

I haven't had time to write an test an Azure specific version, just because I haven't had a lot of demand for it. But your question does tell me there's more interest than I knew of -- so there's that!

I will at minimum look at implementing some error handling so it lets you know in a graceful way though. (This is a bit of a moving target, because Azure has been expanding the features that are available to users as well.)

  • 1
    Since V12 exposes many more DMV's do you think you'll be able to make sp_BlitzIndex work on V12, or is it still missing too many relevant bits to be worthwhile? Provided you have spare time/demand of course. :)
    – Erik
    Commented Dec 7, 2015 at 20:55
  • @Kendra - It'd be really great if this could be updated to work on Azure!! I notice the latest version 20160715 doesn't error when I run sp_BlitzIndex but suspiciously it says there's No major problems found. I suspect this is because required info isn't available in Azure still. When I run with @mode=4 I get an error.
    – Rory
    Commented Jul 27, 2016 at 0:22
  • I'm working on other projects right now, and it's been so long since I've worked on sp_BlitzIndex that I don't know if I'd even recognize the code. But good news, it's open source now! Other people can do it too. You can pitch in at firstresponderkit.org Commented Jul 28, 2016 at 2:14

Some of the 'standard' queries for identifying missing indexes do run on Azure, for example:

  migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure,
  'CREATE INDEX [missing_index_' + CONVERT (varchar, mig.index_group_handle) + '_' + CONVERT (varchar, mid.index_handle)
  + '_' + LEFT (PARSENAME(mid.statement, 1), 32) + ']'
  + ' ON ' + mid.statement
  + ' (' + ISNULL (mid.equality_columns,'')
    + CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END
    + ISNULL (mid.inequality_columns, '')
  + ')'
  + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement,
  migs.*, mid.database_id, mid.[object_id]
FROM sys.dm_db_missing_index_groups mig
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle
WHERE migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) > 10
ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC

They're likely to be much less useful than sp_BlitzIndex but worth a try.

Here's another handy query to identify the top queries, which you can then run with Execution Plan on to identify missing indexes via SQL Management Studio. Tedious doing them one by one but better than nothing:

SELECT TOP 1000 qs.execution_count, 
       qs.total_worker_time / qs.execution_count AS 'Avg CPU Time', 
       qs. total_physical_reads, 
       qs.total_physical_reads / qs.execution_count AS 'Avg Physical Reads', 
       qs.total_logical_reads / qs.execution_count AS 'Avg Logical Reads', 
       qs.total_logical_writes / qs.execution_count AS 'Avg Logical Writes', 
       SUBSTRING(st.text, qs.statement_start_offset / 2 + 1, 
        (CASE qs.statement_end_offset
                     WHEN-1 THEN DATALENGTH(st.text)
                     ELSE qs.statement_end_offset
           - qs.statement_start_offset) / 2 + 1)AS statement_text
  FROM sys.dm_exec_query_stats AS qs 
  CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle)AS st
  ORDER BY qs.execution_count DESC;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.