Mir sind die Parameter-Sniffing-Probleme bekannt, die mit gespeicherten Prozeduren verbunden sind, die mit einem Prädikat wie dem folgenden geschrieben wurden:
CREATE PROCEDURE [dbo].[Get] @Parameter INT = NULL AS BEGIN;
SELECT [Field] FROM [dbo].[Table]
WHERE [Field] = @Parameter
OR @Parameter IS NULL;
END;
Abhängig vom Wert des Parameters Scalar oder NULL bei der ersten Ausführung wird ein Plan zwischengespeichert, der für den entgegengesetzten Wert wahrscheinlich nicht optimal ist.
Angenommen, [Feld] ist skalar und der Clustering-Index für eine Tabelle. Was sind die Vor- und Nachteile der folgenden Ansätze zum Schreiben einer gespeicherten Prozedur (en) zur Unterstützung der Abfrage:
Bedingte Auswahl in derselben gespeicherten Prozedur
CREATE PROCEDURE [dbo].[Get] @Parameter INT = NULL AS BEGIN;
IF(@Parameter IS NOT NULL) BEGIN;
SELECT [Field]
FROM [dbo].[Table]
WHERE [Field] = @Parameter;
END;
ELSE BEGIN;
SELECT [Field]
FROM [dbo].[Table];
END;
END;
Dynamisches SQL innerhalb der gespeicherten Prozedur
CREATE PROCEDURE [dbo].[Get] @Parameter INT = NULL AS BEGIN;
DECLARE @sql NVARCHAR(MAX) = N'';
SET @sql += N'SELECT [Field]'
SET @sql += N'FROM [dbo].[Table]';
IF(@Parameter IS NOT NULL) BEGIN;
@sql += N'WHERE [Field] = @Parameter';
END;
SET @sql += N';';
EXEC sp_executesql @sql N'@Parameter INT', @Parameter;
END;
Getrennte gespeicherte Prozeduren
CREATE PROCEDURE [dbo].[Get] @Parameter INT = NULL AS BEGIN;
SELECT [Field]
FROM [dbo].[Table]
WHERE [Field] = @Parameter;
END;
CREATE PROCEDURE [dbo].[GetAll] AS BEGIN;
SELECT [Field]
FROM [dbo].[Table];
END;
=NULL
werden 0 Zeilen zurückgegeben. Obwohl oft Null-Zeilen-Schätzungen auf 1 aufgerundet werden