我正在查看遗留代码,因为它的表现非常糟糕。 我将问题追踪到了
DECLARE @Parameter AS VARCHAR(50) = '12345'
SELECT *
FROM MyTable
WHERE
(
MyIndexedField IN ( SELECT Value from fn_Function(@Parameter) )
OR @Parameter ISNULL;
)
AND OtherCriteria = 'Something'
查询想要从具有非聚集索引的字段的表中提取所有数据。当我删除OR @Parameter IS NULL时,它会在一秒钟内运行,但是当我添加@Parameter IS NULL时需要40s +。
如果我用文字替换该函数,它会在一秒钟内运行。 实施例
SELECT *
FROM MyTable
WHERE
(
MyIndexedField IN ( '12345' )
OR @Parameter ISNULL;
)
AND OtherCriteria = 'Something'
有什么想法,还有更好的方法可以重写这个查询吗?
这是在SQL 2008上运行
谢谢,
修改
我能够解决问题,但解决方案很奇怪,见下文。 不要认为这是最好的解决方案,如果您有任何建议,我们将不胜感激。
DECLARE @Parameter AS VARCHAR(50) = '12345'
SELECT DISTINCT MyIndexedField
INTO #T
FROM MyTable WHERE @Parameter IS NULL
UNION ALL
SELECT Value FROM fn_Function(@Parameter)
SELECT *
FROM MyTable AS X
JOIN #T AS T ON T.MyIndexedField = X.MyIndexedField
WHERE OtherCriteria = 'Something'
答案 0 :(得分:0)
如果没有看到执行计划并知道fn_Function函数实际上做了什么,很难给出确凿的建议,但是值得探讨的几个想法是:
1)如果你在语句的末尾添加OPTION(RECOMPILE),那么优化器将能够看到' @Parameter参数的值因此能够以' cost'来优化OR @Parameter IS NULL条件(针对此特定输入值)。每次调用此语句时都必须重新编译(而不是存储在执行计划缓存中)。根据呼叫频率/编译成本,这可能是一个可行的策略
2)取决于函数fn_Function的复杂性,您可以在线重新编写它。如果它是一个多语句或内联表值函数,我无法在不看函数的情况下知道,这与此相关。
希望这能给出一些关于要看的内容的指示。