Potresti esserti imbattuto in una query che ha un problema con lo sniffing dei parametri, che ha a che fare con il modo in cui Sql Server tenta di ottimizzare il tuo piano di esecuzione delle query, ma nei casi in cui è coinvolto Reporting Services lo incasina completamente e lo fa funzionare incredibilmente lentamente.
Ho avuto un caso con un rapporto che conteneva due query complesse di circa 150 righe ciascuna ma che sono state eseguite in 7 secondi nel mio ambiente di sviluppo:l'intero rapporto ha richiesto meno di 10 secondi. Tuttavia, quando distribuito nel server SSRS di produzione, il report ha richiesto più di 7 minuti e spesso è scaduto rendendo il report non eseguibile.
La maggior parte delle informazioni su questo problema ne parla in relazione alle stored procedure. Non respingere questo perché non stai utilizzando stored procedure (come ho fatto per molto tempo); è molto rilevante anche per le query SQL semplici.
Quindi la differenza che stai vedendo è che Sql Server sta creando due piani di esecuzione molto diversi poiché le due query sono strutturate in modo diverso.
Fortunatamente, la soluzione è molto semplice:inserisci i parametri nelle variabili interne e usali invece nella tua query. L'ho fatto con il mio report e il report di produzione è tornato a 10 secondi come faceva la versione di sviluppo in Visual Studio.
Per ignorare lo sniffing dei parametri per la tua prima query, dovresti farlo assomigliare a questo:
BEGIN
-- Use internal variables to solve parameter sniffing issues
DECLARE @StartDateInternal AS DATETIME;
DECLARE @EndDateInternal AS DATETIME;
DECLARE @SchoolIDInternal AS INT;
DECLARE @GradeLevelInternal AS INT;
-- Copy the parameters into the internal variables
SET @StartDateInternal = @StartDate;
SET @EndDateInternal = @EndDate;
SET @SchoolIDInternal = @SchoolID;
SET @GradeLevelInternal = @GradeLevel;
-- Now use the internal variables in your query rather than the parameters
SELECT
c.TeacherID, u.FName + ' ' + u.lname as Teacher, count(sb.behaviorID) as BxCount,
sb.behaviorID, b.BehaviorName, std.GradeID, gl.GradeLevel
FROM
StudentBehaviors sb
join
Classes c on sb.classid = c.classid
join
StudentDetails std on sb.studentID = std.StudentID and std.RecordIsActive=1
join
users u on c.TeacherID = u.UserID
join
Behaviors b on sb.behaviorID = b.BehaviorID
join
GradeLevels gl on std.GradeID = gl.GradeLevelID
WHERE
sb.classdate between @StartDateInternal and @EndDateInternal
and c.schoolid = @SchoolIDInternal
and std.GradeID = @GradeLevelInternal
GROUP BY
c.TeacherID, sb.behaviorID, b.BehaviorName, u.lname, u.FName,
std.GradeID, gl.GradeLevel
ORDER BY
u.LName, sb.behaviorID;
END;