我继承了一个存储过程并且遇到问题需要很长时间才能运行(大约3分钟)。我玩过它,没有where子句它实际上只需要12秒就可以运行。它引用的表中都没有大量数据,任何人都可以看到为什么在下面添加main where子句需要更长的时间?
ALTER Procedure [dbo].[MissingReadingsReport] @SiteID INT,
@FormID INT,
@StartDate Varchar(8),
@EndDate Varchar(8)
As
If @EndDate > GetDate()
Set @EndDate = Convert(Varchar(8), GetDate(), 112)
Select Dt.FormID,
DT.FormDAte,
DT.Frequency,
Dt.DayOfWeek,
DT.NumberOfRecords,
Dt.FormName,
dt.OrgDesc,
Dt.CDesc
FROM (Select MeterForms.FormID,
MeterForms.FormName,
MeterForms.SiteID,
MeterForms.Frequency,
DateTable.FormDate,
tblOrganisation.OrgDesc,
CDesc = ( COMPANY.OrgDesc ),
DayOfWeek = CASE Frequency
WHEN 'Day' THEN DatePart(dw, DateTable.FormDate)
WHEN 'WEEK' THEN
DatePart(dw, MeterForms.FormDate)
END,
NumberOfRecords = CASE Frequency
WHEN 'Day' THEN (Select TOP 1 RecordID
FROM MeterReadings
Where
MeterReadings.FormDate =
DateTable.FormDate
And MeterReadings.FormID =
MeterForms.FormID
Order By RecordID DESC)
WHEN 'WEEK' THEN (Select TOP 1 ( FormDate )
FROM MeterReadings
Where
MeterReadings.FormDate >=
DateAdd(d
, -4,
DateTable.FormDate)
And MeterReadings.FormDate
<=
DateAdd(d, 3,
DateTable.FormDate)
AND MeterReadings.FormID =
MeterForms.FormID)
END
FROM MeterForms
INNER JOIN DateTable
ON MeterForms.FormDate <= DateTable.FormDate
INNER JOIN tblOrganisation
ON MeterForms.SiteID = tblOrganisation.pkOrgId
INNER JOIN tblOrganisation COMPANY
ON tblOrganisation.fkOrgID = COMPANY.pkOrgID
/*this is what makes the query run slowly*/
Where DateTable.FormDAte >= @StartDAte
AND DateTable.FormDate <= @EndDate
AND MeterForms.SiteID = ISNULL(@SiteID, MeterForms.SiteID)
AND MeterForms.FormID = IsNull(@FormID, MeterForms.FormID)
AND MeterForms.FormID > 0)DT
Where ( Frequency = 'Day'
And dt.NumberofRecords IS NULL )
OR ( ( Frequency = 'Week'
AND DayOfWeek = DATEPART (dw, Dt.FormDate) )
AND ( FormDate <> NumberOfRecords
OR dt.NumberofRecords IS NULL ) )
Order By FormID
答案 0 :(得分:2)
根据您已经提到过的内容,看起来表格是为连接条件中的列正确编制索引的,而不是where子句中的列。
如果您不愿意更改查询,那么查看where子句列中定义的索引可能是值得的,特别是具有NULL检查的索引
答案 1 :(得分:0)
我愿意打赌,如果你把Meterforms的条款移到了以下声明中:
FROM (select [columns] from MeterForms WHERE SiteID= ISNULL [etc] ) MF
INNER JOIN [etc]
它会更快,因为过滤会在连接之前发生。此外,让你的DateTable上的INNER JOIN在你的where子句中执行&lt; = down可能会返回比你想要的更多...尝试将其移动到子选择之间。
您是否在此处运行执行计划,看看瓶颈在哪里?
答案 2 :(得分:0)
随机建议,来自Oracle背景:
如果您重写以下内容会发生什么:
AND MeterForms.SiteID = ISNULL(@SiteID, MeterForms.SiteID)
AND MeterForms.FormID = IsNull(@FormID, MeterForms.FormID)
...至
AND (@SiteID is null or MeterForms.SiteID = @SiteID)
AND (@FormID is null or MeterForms.FormID = @FormID)
答案 3 :(得分:0)
尝试用以下内容替换您的选择:
FROM
(select siteid, formid, formdate from meterforms
where siteid = isnull(@siteid, siteid) and
meterforms.formid = isnull(@formid, formid) and formid >0
) MeterForms
INNER JOIN
(select formdate from datetable where formdate >= @startdate and formdate <= @enddate) DateTable
ON MeterForms.FormDate <= DateTable.FormDate
INNER JOIN tblOrganisation
ON MeterForms.SiteID = tblOrganisation.pkOrgId
INNER JOIN tblOrganisation COMPANY
ON tblOrganisation.fkOrgID = COMPANY.pkOrgID
/*this is what makes the query run slowly*/
)DT