• My fix to this was just to replace the FROM statement that has the ranking function with the original FROM statement. I know it was probably a bug fix, but it was a matter of potentially having the plan count wrong and being able to generate the report in 5 seconds vs having the correct plan count right and waiting 8 minutes.

    Or, here is the 2008 R2 version of the procedure that you could just run on your 2012 Management Data Warehouse database (make sure you make a copy of the original just in case):

    ALTER PROCEDURE [snapshots].[rpt_query_stats]

    @instance_name sysname,

    @start_time datetime = NULL,

    @end_time datetime = NULL,

    @time_window_size smallint,

    @time_interval_min smallint = 1,

    @sql_handle_str varchar(130),

    @statement_start_offset int,

    @statement_end_offset int

    AS

    BEGIN

    SET NOCOUNT ON;

    -- @end_time should never be NULL when we are called from the Query Stats report

    -- Convert snapshot_time (datetimeoffset) to a UTC datetime

    IF (@end_time IS NULL)

    SET @end_time = CONVERT (datetime, SWITCHOFFSET (CAST ((SELECT MAX(snapshot_time) FROM core.snapshots) AS datetimeoffset(7)), '+00:00'));

    IF (@start_time IS NULL)

    BEGIN

    -- If time_window_size and time_interval_min are set use them

    -- to determine the start time

    -- Otherwise use the earliest available snapshot_time

    IF @time_window_size IS NOT NULL AND @time_interval_min IS NOT NULL

    BEGIN

    SET @start_time = DATEADD(minute, @time_window_size * @time_interval_min * -1.0, @end_time);

    END

    ELSE

    BEGIN

    -- Convert min snapshot_time (datetimeoffset) to a UTC datetime

    SET @start_time = CONVERT (datetime, SWITCHOFFSET (CAST ((SELECT MIN(snapshot_time) FROM core.snapshots) AS datetimeoffset(7)), '+00:00'));

    END

    END

    DECLARE @end_snapshot_time_id int;

    SELECT @end_snapshot_time_id = MAX(snapshot_time_id) FROM core.snapshots WHERE snapshot_time <= @end_time;

    DECLARE @start_snapshot_time_id int;

    SELECT @start_snapshot_time_id = MIN(snapshot_time_id) FROM core.snapshots WHERE snapshot_time >= @start_time;

    DECLARE @interval_sec int;

    SET @interval_sec = DATEDIFF (s, @start_time, @end_time);

    DECLARE @sql_handle-2 varbinary(64)

    SET @sql_handle-2 = snapshots.fn_hexstrtovarbin (@sql_handle_str)

    SELECT

    REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (REPLACE (

    LEFT (LTRIM (stmtsql.query_text), 100)

    , CHAR(9), ' '), CHAR(10), ' '), CHAR(13), ' '), ' ', ' '), ' ', ' '), ' ', ' ') AS flat_query_text,

    t.*,

    master.dbo.fn_varbintohexstr (t.sql_handle) AS sql_handle_str,

    stmtsql.*

    FROM

    (

    SELECT

    stat.sql_handle, stat.statement_start_offset, stat.statement_end_offset, snap.source_id,

    SUM (stat.snapshot_execution_count) AS execution_count,

    SUM (stat.snapshot_execution_count) / (@interval_sec / 60) AS executions_per_min,

    SUM (stat.snapshot_worker_time / 1000) AS total_cpu,

    SUM (stat.snapshot_worker_time / 1000) / @interval_sec AS avg_cpu_per_sec,

    SUM (stat.snapshot_worker_time / 1000.0) / CASE SUM (stat.snapshot_execution_count) WHEN 0 THEN 1 ELSE SUM (stat.snapshot_execution_count) END AS avg_cpu_per_exec,

    SUM (stat.snapshot_physical_reads) AS total_physical_reads,

    SUM (stat.snapshot_physical_reads) / @interval_sec AS avg_physical_reads_per_sec,

    SUM (stat.snapshot_physical_reads) / CASE SUM (stat.snapshot_execution_count) WHEN 0 THEN 1 ELSE SUM (stat.snapshot_execution_count) END AS avg_physical_reads_per_exec,

    SUM (stat.snapshot_logical_writes) AS total_logical_writes,

    SUM (stat.snapshot_logical_writes) / @interval_sec AS avg_logical_writes_per_sec,

    SUM (stat.snapshot_logical_writes) / CASE SUM (stat.snapshot_execution_count) WHEN 0 THEN 1 ELSE SUM (stat.snapshot_execution_count) END AS avg_logical_writes_per_exec,

    SUM (stat.snapshot_elapsed_time / 1000) AS total_elapsed_time,

    SUM (stat.snapshot_elapsed_time / 1000) / @interval_sec AS avg_elapsed_time_per_sec,

    SUM (stat.snapshot_elapsed_time / 1000.0) / CASE SUM (stat.snapshot_execution_count) WHEN 0 THEN 1 ELSE SUM (stat.snapshot_execution_count) END AS avg_elapsed_time_per_exec,

    COUNT(*) AS row_count, COUNT (DISTINCT stat.creation_time) AS plan_count

    FROM snapshots.query_stats AS stat

    INNER JOIN core.snapshots snap ON stat.snapshot_id = snap.snapshot_id

    WHERE

    snap.instance_name = @instance_name

    AND stat.sql_handle = @sql_handle-2

    AND stat.statement_start_offset = @statement_start_offset

    AND stat.statement_end_offset = @statement_end_offset

    AND snap.snapshot_time_id BETWEEN @start_snapshot_time_id AND @end_snapshot_time_id

    GROUP BY stat.sql_handle, stat.statement_start_offset, stat.statement_end_offset, snap.source_id

    ) t

    LEFT OUTER JOIN snapshots.notable_query_text sql ON t.sql_handle = sql.sql_handle and sql.source_id = t.source_id

    OUTER APPLY snapshots.fn_get_query_text (t.source_id, t.sql_handle, t.statement_start_offset, t.statement_end_offset) AS stmtsql

    -- These trace flags are necessary for a good plan, due to the join on ascending PK w/range filter

    OPTION (QUERYTRACEON 2389, QUERYTRACEON 2390)

    END

    GO

    Hopefully this will get fixed in an upcoming patch of 2012.