我正在编写一个通用搜索存储过程,以根据用户可以在 UI 中选择的许多过滤器(使用 MS-SQL 2008)在表中搜索。
这是简化版本:
CREATE PROCEDURE SearchAll
@FirstName NVARCHAR(MAX) = NULL,
@LastName NVARCHAR(MAX) = NULL,
@Age INT = NULL
AS
SELECT *
FROM persons
WHERE
(@FirstName IS NULL OR FirstName = @firstname)
AND (@LastName IS NULL OR LastName = @LastName)
AND (@Age IS NULL OR Age = @Age)
似乎如果我将 NULL 传递给 @Age 就不会有性能成本。但是,当我使用大量数据进行测试时,我失去了很大的性能!
这是逻辑上相同但实际上非常不同的查询:
DECLARE @FirstName NVARCHAR(MAX) = NULL
DECLARE @Age INT = 23
------------First slow------------
SELECT *
FROM persons
WHERE
(@FirstName IS NULL OR FirstName = @firstname)
AND (@Age IS NULL OR Age = @Age)
------------Very fast------------
SELECT *
FROM persons
WHERE
Age = @Age
有没有漏掉一点?
我知道 SQL 引擎会找到索引的最佳匹配,并且...(在运行查询之前),但很明显:@FirstName IS NULL
并且不需要分析任何内容。
我还在ISNULL
查询中测试了函数(结果相同)。