2015-10-08 153 views
0

我正试图优化一个存储过程,此时此刻很慢。它需要几个参数来搜索哪些可以为空。 SP中的查询看起来像这样。SQL查询优化(搜索)

SELECT 
    *some fields from the table* 
FROM 
    [hrmCase] 
WHERE 
    BrkId = @BrkId 
AND 
    (ChannelId IN ('TO','TD')) 
AND 
    case 
     when @PsId is null then 1 
     when (@PsId is not null) and ((SELECT SUBSTRING(UPPER(DATENAME(MONTH, Created)),1,3) + CAST(PSId AS varchar) PSId) like ('%' + @PsId + '%')) then 1 else 0 
    end = 1 
AND 
    case 
     when @ACaseId is null then 1 
     when (@ACaseId is not null) and (AId like ('%' + @ACaseId + '%')) then 1 else 0 
    end = 1 
AND    
    case 
     when @DateCreated is null then 1 
     when (@DateCreated is not null) and (dbo.StripTime(Created) = dbo.StripTime(@DateCreated)) then 1 else 0 
    end = 1 
AND 
    case 
     when @Clients is null then 1 
     when (@Clients is not null) and (Client like ('%' + @Clients + '%')) then 1 else 0 
    end = 1 

这是做的最好的方式还是应该建立一个基于输入参数动态查询像下面

Declare @SQLQuery AS NVarchar(4000) 
Declare @ParamDefinition AS NVarchar(2000) 

Set @SQLQuery = 'SELECT *some fields from the table* FROM [hrmCase] WHERE (1=1)' 

If @PsId Is Not Null 
    Set @SQLQuery = @SQLQuery + ' And (SELECT SUBSTRING(UPPER(DATENAME(MONTH, Created)),1,3) + CAST(PSId AS varchar) PSId) like (''%''' + @PsId + '''%'')' 

etc.. 

这被认为更加专业和上述两个查询的速度会更快。请建议是否有更好的方法来做同样的事情。

干杯, DS

+0

在每种情况下,您都使用函数或'LIKE%短语%',以便您的查询不是SARGable,并且查询优化器不会在任何存在的情况下使用idexes。没有使用索引=糟糕的表现。 – lad2025

+0

当条件可以使用索引时,动态查询几乎总是更好。在你的情况下,条件不能。所以,动态版本会稍微快一点,因为查询的复杂比较会少一些。但它可能不会有很大的不同。 –

+0

不能帮助它。大多数列是文本列,我们允许部分搜索。 – SkoolCodeian

回答

0

SQL Server是非常糟糕时,使用参数处理这样的 - 我们已经有很多情况下,我们得到它可接受,然后工作4个月后,有新的变化,并将其变成表扫描(或者更糟 - 我看到性能远远低于简单表扫描)。 (我们在镜像的40核心服务器上的SSD上有1.5TB数据库)。我们发现的最佳解决方案是使用单独的存储过程或使用动态SQL。许多“专家”都对动态SQL感到不满,但现实情况是,如今在任何体面的环境中,动态SQL的重新编译在CPU使用和性能延迟方面都是微不足道的,它消除了因为消除而出现的问题类型WHERE子句中的条件会混淆查询优化器。

领先的通配符在每种情况下也会导致表扫描。全文索引可以比常规SQL更有效地执行此类搜索。一些SQL Server支持全文索引和查询,有些则不支持。