如何降低 CASE 表达式的执行成本?[关闭]

How can I decrease the execution cost of my CASE expressions? [closed]

提问人:SkyeBoniwell 提问时间:11/16/2023 最后编辑:XedniSkyeBoniwell 更新时间:11/16/2023 访问量:69

问:


想改进这个问题吗?通过编辑这篇文章添加详细信息并澄清问题。

4天前关闭。

截至 4 天前,社区正在审查是否重新打开此问题。

我的查询中有这个CASE表达式:

    CASE el.faunaType
        WHEN 2 THEN 'Examine "' + ISNULL((SELECT TOP 1 cellComplex FROM cellList WHERE TRY_CONVERT(NVARCHAR(50), cellID) = TRY_CONVERT(NVARCHAR(50), faunaSource)), '') + '"'
        WHEN 9 THEN 'Investigate "' + (SELECT TOP 1 sourceText FROM diseaseSources WHERE TRY_CONVERT(NVARCHAR(50), sourceID) = TRY_CONVERT(NVARCHAR(50), faunaSource)) + '"'
        WHEN 15 THEN 'Infection detected "' + (SELECT TOP 1 sourceText FROM diseaseSources WHERE TRY_CONVERT(NVARCHAR(50), sourceID) = TRY_CONVERT(NVARCHAR(50), faunaSource)) + '"'
        WHEN 23 THEN 'Forward on "' + (SELECT TOP 1 cellComplex FROM cellList WHERE TRY_CONVERT(NVARCHAR(50), cellID) = TRY_CONVERT(NVARCHAR(50), faunaSource)) + '"'
        WHEN 45 THEN 'Traced cell "' + ISNULL((SELECT TOP 1 cellComplex FROM cellList WHERE TRY_CONVERT(NVARCHAR(50), cellID) = TRY_CONVERT(NVARCHAR(50), faunaSource)), '') + '"'
        WHEN 77 THEN 'Sampled on "' + (SELECT TOP 1 cellComplex FROM cellList WHERE TRY_CONVERT(NVARCHAR(50), cellID) = TRY_CONVERT(NVARCHAR(50), faunaSource)) + '"<br />[' + faunaMessage + ']'
    END As FaunaName

此块对性能造成了巨大的影响。当我查看执行计划时,我看到 和 20% 的成本。diseaseSourcescellList

它正在执行聚簇索引扫描。

我将这两个表的 ID(cellID 和 sourceID)作为主键。

有没有办法降低这个 CASE 语句的性能成本?

sql-server t-sql sql-server-2012

评论

3赞 Xedni 11/16/2023
所以你要查询一堆表,这总是会有些成本。另一个问题是,您调用了所有表列,这使得查询无法使用索引(它不知道列的转换版本索引与未更改的列的索引相同)。如果是我,我会先将所有这些值分配给变量,并尝试在不转换列的情况下获取这些值。此外,您击中了同一张桌子 () 4 次。一次性获取所有这些值。try_convertcellList
2赞 Xedni 11/16/2023
此外,查看该 case 语句周围的内容会很有帮助,因为您可能以非最佳方式查询它。我建议扩展您的代码片段,以便我们可以看到整个查询;不仅仅是案例陈述。
7赞 Thom A 11/16/2023
没有 a 也是缺陷的标志;返回的值将是完全任意的,并且每次运行查询时都可能不同。TOP (1)ORDER BY
2赞 Thom A 11/16/2023
此外,您不会限定子查询中的列;我假设这意味着所有列都是为了引用子查询中定义的表?例如(没有“噪音”),你的意思是?如果你不这样做,那么你真的应该养成对对象进行别名化和限定列的习惯。否则,你将在代码中遇到 bug,而不是 T-SQLSELECT cL.cellComplex FROM dbo.cellList cL WHERE cL.cellID = cL.faunaSource
3赞 TT. 11/16/2023
我有一种感觉,如果你愿意发布你的完整查询,就像你应该的那样,因为我们现在只是在猜测,我们会被一个长度没有结束并且在每个角落和缝隙中都有复杂结构的查询所震撼。在任何情况下,您现在都会在外部查询中选择每行启动一个完整查询...那可能不是你想做的。您可能应该在外部查询中联接这些表。

答:

2赞 Gavin Clayton 11/16/2023 #1

生成 HTML 的表结构有点猜测,但你最好加入一次,然后改变你处理 SQL 的方式。在您的示例中,您将为每个情况执行唯一的 select 语句,而联接执行一次匹配,然后处理显示。

DECLARE @FT TABLE(faunaType NVARCHAR(100),faunaSource NVARCHAR(50),faunaMessage NVARCHAR(100))
DECLARE @CL TABLE(cellID NVARCHAR(50),cellComplex NVARCHAR(100))
DECLARE @DS TABLE(sourceID NVARCHAR(50),sourceText NVARCHAR(100))

SELECT *,
    CASE el.faunaType
        WHEN 2 THEN 'Examine "' + ISNULL((SELECT TOP 1 cellComplex FROM @CL WHERE TRY_CONVERT(NVARCHAR(50), cellID) = TRY_CONVERT(NVARCHAR(50), faunaSource)), '') + '"'
        WHEN 9 THEN 'Investigate "' + (SELECT TOP 1 sourceText FROM @DS WHERE TRY_CONVERT(NVARCHAR(50), sourceID) = TRY_CONVERT(NVARCHAR(50), faunaSource)) + '"'
        WHEN 15 THEN 'Infection detected "' + (SELECT TOP 1 sourceText FROM @DS WHERE TRY_CONVERT(NVARCHAR(50), sourceID) = TRY_CONVERT(NVARCHAR(50), faunaSource)) + '"'
        WHEN 23 THEN 'Forward on "' + (SELECT TOP 1 cellComplex FROM @CL WHERE TRY_CONVERT(NVARCHAR(50), cellID) = TRY_CONVERT(NVARCHAR(50), faunaSource)) + '"'
        WHEN 45 THEN 'Traced cell "' + ISNULL((SELECT TOP 1 cellComplex FROM @CL WHERE TRY_CONVERT(NVARCHAR(50), cellID) = TRY_CONVERT(NVARCHAR(50), faunaSource)), '') + '"'
        WHEN 77 THEN 'Sampled on "' + (SELECT TOP 1 cellComplex FROM @CL WHERE TRY_CONVERT(NVARCHAR(50), cellID) = TRY_CONVERT(NVARCHAR(50), faunaSource)) + '"<br />[' + faunaMessage + ']'
    END As FaunaName
FROM @FT el

SELECT *,
    CASE el.faunaType
        WHEN 2 THEN 'Examine "' + ISNULL(cellComplex, '') + '"'
        WHEN 9 THEN 'Investigate "' + ISNULL(sourceText, '') + '"'
        WHEN 15 THEN 'Infection detected "' + ISNULL(sourceText, '') + '"'
        WHEN 23 THEN 'Forward on "' + ISNULL(cellComplex, '') + '"'
        WHEN 45 THEN 'Traced cell "' + ISNULL(cellComplex, '') + '"'
        WHEN 77 THEN 'Sampled on "' + ISNULL(cellComplex, '') + '"<br />[' + faunaMessage + ']'
    END As FaunaName
FROM @FT el 
LEFT JOIN @DS ds ON ds.sourceID=el.faunaSource
LEFT JOIN @CL cl ON cl.cellID=el.faunaSource