为什么在存储过程中再添加一个参数会使其变得非常慢

时间:2016-12-01 20:44:49

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

我有一个包含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,','))     
    )...

这是我正在使用的数据:

enter image description here

2 个答案:

答案 0 :(得分:1)

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

您应该整理列(make database normalization)。你索引。

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

如果你不想改变你的qry,那么改变执行计划,重写为派生的qry。

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

请尽量避免使用*

答案 1 :(得分:0)

而不是

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秒