SQL (ISNULL(@parameter) OR @parameter > Column) 模式的查询优化器以及它是否针对@parameter 为空时进行优化

SQL query optimiser for (ISNULL(@parameter) OR @parameter > Column) patterns and whether it optimises for when @parameter is null

如果我有一个表单,用户可以在其中指定一堆过滤器(例如 productid > 5,category = "Applicances",Price > 3),那么制作一个准备好的语句似乎很自然:

SELECT * 
FROM Products
WHERE 
  (@Price IS NULL OR Price > @Price) AND
  (@Category IS NULL OR @Category = Category) AND
  (@ProductID IS NULL OR Price > @Product);

然后添加@Price、@Category 和@ProductID 作为参数,当用户没有在表单中输入任何内容时,这些参数为空。

但是,查询优化器是否足够聪明,可以在@Category 和@ProductID 为空时仅使用价格索引?这是因为您将拥有条件 (ISNULL(NULL) OR NULL = Category),它始终为真。例如。它做的事情是否与 if:

完全相同
SELECT * 
FROM Products 
WHERE Price > @Price

准备好了吗?

是否取决于使用的 SQL 引擎? (SQL 服务器,MySQL,SQLite,甲骨文,Postgres)

is the Query Optimiser clever enough for when @Category and @ProductID is null, to only use an Index for the Price?

通常,多个列上的 andor 的组合会提示索引使用情况。在某些数据库中,可以为单个 where 子句使用多个索引。

但是,将查询构建为动态 SQL 可能会更好。 SQL 服务器中的类似内容(与您提供的代码最相似):

DECLARE @sql NVARCHAR(MAX) = '
SELECT * 
FROM Products
WHERE 1=1';

IF (@Price IS NOT NULL)
BEGIN
    SET @SQL = @SQL + ' Price > @Price'
END;

. . .

然后您可以使用sp_executesql传递参数。

本质上,代码创建了一系列查询——取决于参数——然后每个查询都可以单独优化。