【发布时间】:2016-11-29 18:48:57
【问题描述】:
我目前在 MSSQL 中有一个存储过程,我根据给存储过程的变量多次执行 SELECT 语句。存储过程计算用户可以启用的每个过滤器将返回多少结果。 存储过程不是问题,我将 select 语句从 te 存储过程转换为常规的 select 语句,如下所示:
DECLARE @contentRootId int = 900589
DECLARE @RealtorIdList varchar(2000) = ';880;884;1000;881;885;'
DECLARE @publishSoldOrRentedSinceDate int = 8
DECLARE @isForSale BIT= 1
DECLARE @isForRent BIT= 0
DECLARE @isResidential BIT= 1
--...(another 55 variables)...
--Table to be returned
DECLARE @resultTable TABLE
(
variableName varchar(100),
[value] varchar(200)
)
-- Create table based of inputvariable. Example: turns ';18;118;' to a table containing two ints 18 AND 118
DECLARE @RealtorIdTable table(RealtorId int)
INSERT INTO @RealtorIdTable SELECT * FROM dbo.Split(@RealtorIdList,';') option (maxrecursion 150)
INSERT INTO @resultTable ([value], variableName)
SELECT [Value], VariableName FROM(
Select count(*) as TotalCount,
ISNULL(SUM(CASE WHEN reps.ForRecreation = 1 THEN 1 else 0 end), 0) as ForRecreation,
ISNULL(SUM(CASE WHEN reps.IsQualifiedForSeniors = 1 THEN 1 else 0 end), 0) as IsQualifiedForSeniors,
--...(A whole bunch more SUM(CASE)...
FROM TABLE1 reps
LEFT JOIN temp t on
t.ContentRootID = @contentRootId
AND t.RealEstatePropertyID = reps.ID
WHERE
(EXISTS(select 1 from @RealtorIdTable where RealtorId = reps.RealtorID))
AND (@SelectedGroupIds IS NULL OR EXISTS(select 1 from @SelectedGroupIdtable where GroupId = t.RealEstatePropertyGroupID))
AND (ISNULL(reps.IsForSale,0) = ISNULL(@isForSale,0))
AND (ISNULL(reps.IsForRent, 0) = ISNULL(@isForRent,0))
AND (ISNULL(reps.IsResidential, 0) = ISNULL(@isResidential,0))
AND (ISNULL(reps.IsCommercial, 0) = ISNULL(@isCommercial,0))
AND (ISNULL(reps.IsInvestment, 0) = ISNULL(@isInvestment,0))
AND (ISNULL(reps.IsAgricultural, 0) = ISNULL(@isAgricultural,0))
--...(Around 50 more of these WHERE-statements)...
) as tbl
UNPIVOT (
[Value]
FOR [VariableName] IN(
[TotalCount],
[ForRecreation],
[IsQualifiedForSeniors],
--...(All the other things i selected in above query)...
)
) as d
select * from @resultTable
Realtor- 和 contentID 的组合为我提供了一组默认的 X 条记录。当我选择一个给我约 4600 条记录的组合时,执行时间约为 250 毫秒。当我使用给我〜600条记录的组合执行sattement时,执行时间约为20ms。
我想知道为什么会这样。我尝试删除选择中的所有 SUM(CASE,尝试从 WHERE 子句中删除几乎所有内容,并尝试删除 JOIN。但我一直看到 4600 和 600 的结果集之间存在巨大差异。
【问题讨论】:
-
检查参数嗅探并添加
OPTION(RECOMPILE)。您还可以更新表格上的统计信息。 BTW 请提供两种情况的执行计划 -
我不确定您所说的“您还可以更新表格上的统计信息”是什么意思。我尝试了参数嗅探,它有帮助,但不是很多。我会检查选项(重新编译)
-
ISNULL(reps.IsForSale,0) = ISNULL(@isForSale,0)- 这些isnulls 也是问题。你最好改写成(@isforsale is null or isforsale=@isforsale)+重新编译 -
更改 ISNULL 并没有多大作用。重新编译对较大的结果集没有任何作用,但会使较小的结果集变慢。
-
为表和索引添加实际执行计划和DDL。
标签: sql-server performance tsql stored-procedures