【问题标题】:Why adding one more parameter to the Stored Procedure makes it very slow为什么向存储过程添加一个参数会使它变得非常慢
【发布时间】:2017-04-16 15:28:55
【问题描述】:

我有一个带有 5 个参数 @State,@StartDate,@EndDate,@AsOfDate,@SICCode 的 SP。如果我执行 SP 并提供参数,它会在 1 秒内返回数据。 然后,如果我添加另一个参数@Coverage,那么执行它需要大约 17 秒。

我查看了带有和不带有@Coverage 参数的缓存计划,看起来它看起来一样。 我使用了调优顾问并创建了所有可能的索引。

如果我运行与 SELECT 语句相同的代码并提供与 WHERE 子句中的参数相同的值 - 那么我得到了大约 1 秒的结果。 那么为什么只有当我添加这个确切的一个参数@Coverage 时才会如此显着地降低性能呢?

如果它是一个参数嗅探,那么我如何确定它是?有什么方法可以检查吗?

ALTER PROCEDURE [dbo].[EarningPlazaCommercial] 
@State varchar(50),
@StartDate datetime,
@EndDate datetime,
@AsOfDate datetime,
@SICCode nvarchar(max),
@Coverage varchar(100)

AS
BEGIN
SET NOCOUNT ON;
    CREATE TABLE #PolicyNumbers  (PolicyNumber varchar(50))
    INSERT INTO #PolicyNumbers SELECT  PolicyNumber FROM PlazaInsuranceWPDataSet WHERE SICCode IN (SELECT * FROM [dbo].[StringOfStringsToTable](@SICCode,','))-- ('0161','0173','0179','0181','0191','0722','0752','0761','0782','1440','1441','1442','1521','1522','161','1611','1629','1711','172','1731','1742') 
    CREATE CLUSTERED INDEX IDX_C_PolicyNumbers_PolicyNumber ON #PolicyNumbers(PolicyNumber) 
    ; WITH Earned_to_date AS (
       SELECT Cast(@AsOfDate AS DATE) AS Earned_to_date
    ), policy_data AS (
        SELECT
            PolicyNumber,
            Coverage
    ,       Cast(PolicyEffectiveDate AS DATE) AS PolicyEffectiveDate
    ,       Cast(PolicyExpirationDate AS DATE) AS PolicyExpirationDate
    ,       WrittenPremium
    --,     --State
            FROM PlazaInsuranceWPDataSet piwp
            WHERE   EXISTS (SELECT PolicyNumber FROM #PolicyNumbers pn WHERE pn.PolicyNumber = piwp.PolicyNumber) 
                    AND Coverage IN (SELECT * FROM [dbo].[StringOfStringsToTable](@Coverage,','))
                    AND State IN (SELECT * FROM [dbo].[StringOfStringsToTable](@State,','))     
    )...

这是我正在处理的数据:

【问题讨论】:

  • coverage 列有索引吗?
  • this 有帮助吗?
  • 看起来您在 Where 子句中进行了 2 个函数拆分。将字符串拆分为存储过程顶部的临时表,然后改为引用临时表。
  • M.Ali 是的,我在 Coverage 列上有索引。谢谢
  • 你的 StringOfStringsToTable 函数是什么样的?我有一种感觉,这将成为你表现不佳的罪魁祸首。

标签: sql-server tsql stored-procedures parameter-passing


【解决方案1】:

代替

WHERE   EXISTS (SELECT PolicyNumber FROM #PolicyNumbers pn WHERE pn.PolicyNumber = piwp.PolicyNumber) 
                    AND Coverage IN (SELECT * FROM [dbo].[StringOfStringsToTable](@Coverage,','))
                    AND State IN (SELECT * FROM [dbo].[StringOfStringsToTable](@State,','))

我在#PolicyNumbers 中插入了由所有参数过滤的所有策略编号 然后用了

WHERE   EXISTS (SELECT PolicyNumber FROM #PolicyNumbers pn WHERE pn.PolicyNumber = piwp.PolicyNumber)

结果显示在 ~1 秒内

【讨论】:

    【解决方案2】:

    这是因为您正在处理字符串。没有索引。逻辑复杂。

    你应该组织你的专栏(make database normalization)。你索引。

    您应该使用集合论而不是使用组合字符串。

    如果您不想对您的 qry 进行太多更改,请更改执行计划并重写为派生的 qry。

    select * 
    from (select ...) t 
    where Coverage (SELECT KeyCol FROM [dbo].[StringOfStringsToTable](@Coverage,','))
    

    请尽量避免使用*

    【讨论】:

    • 我试过了。不幸的是,它没有帮助。但是你说的字符串工作是什么意思?和“使用集合论而不是使用组合字符串”?谢谢
    • 对于整个集合,将您的字符串拆分为一个表(键;字符串)。对于第二组将字符串拆分为一个表(key2; string2)...将整个集合与分解的表连接在一起。您也可以使用视图。但是你应该先分解你的字符串。尝试使用选项重新编译运行您的过程。
    • 嘿,谢谢你的想法。我通过使用所有参数将所有内容放入#TempTable 中来实现它。然后WHERE EXISTS (SELECT PolicyNumber FROM #PolicyNumbers pn WHERE pn.PolicyNumber = piwp.PolicyNumber) 在~1 秒内得到结果。再次感谢
    猜你喜欢
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 2015-11-20
    • 1970-01-01
    相关资源
    最近更新 更多