我有一个查询,目前只有324条记录需要10秒钟才能提高性能。请注意,我对Sql Server还是很陌生。
已尝试:
我已经在SP中使用SET NOCOUNT ON
,因为我已经知道它可以提高性能,甚至每个表都使用alias
。请让我知道可以采取哪些措施来改善其性能
DECLARE @vRequestedBy VARCHAR(2000) = CASE WHEN @RequestedBy <> '' THEN @RequestedBy END,
@vJobType NVARCHAR(2000) = CASE WHEN @JobType <> '' THEN @JobType END;
SELECT distinct ts.JobID,
dbo.TSP_CAT_Category.Category,
ts.JobType,
dbo.TSP_TSR_JobStatus.JobStatus,
dbo.wsm_Contact.Name "ContactName",
ts.Created,
wb.Name AS BuildingName,
ts.Contact,
ts.CreatedBy,
ts.ContactEmail,
dbo.wsm_Contact.TradingAs,
--wsm_Contact_User.UserId "RequestedByUserId",
c2.Name "RequestedByUser",
dbo.wsm_Contact.ContactID
FROM
dbo.TSP_TSR_Job ts
LEFT OUTER JOIN
dbo.wsm_Ref_Buildings wb ON ts.BuildingID = wb.BuildingId
LEFT OUTER JOIN
dbo.wsm_Contact ON ts.TenancyID = dbo.wsm_Contact.ContactID
LEFT OUTER JOIN
dbo.TSP_TSR_JobStatus ON ts.JobStatusID = dbo.TSP_TSR_JobStatus.JobStatusID
LEFT OUTER JOIN
dbo.TSP_CAT_Category ON ts.CategoryID = dbo.TSP_CAT_Category.CategoryID
LEFT OUTER JOIN
dbo.wsm_Contact_User ON UserID = ts.ContactEmail COLLATE SQL_Latin1_General_CP1_CI_AS
LEFT OUTER JOIN
wsm_Contact c2 ON c2.ContactID = wsm_Contact_User.ContactID
WHERE
-- JobId criteria
(@JobID = 0 OR JobID = @JobId)
AND (@TenancyId = '0' OR TenancyId in (select Item from Split_fn(@TenancyID,',')))
AND (@TradingAs = '0' OR wsm_Contact.ContactID in (select Item from Split_fn(@TradingAs,',') ))
--RequestedBy
AND (@vRequestedBy IS NULL OR @vRequestedBy = '0' OR ts.ContactEmail in (Select distinct Email from dbo.wsm_Contact WHere Email in (select Item from Split_fn(@vRequestedBy,',')) ))
-- Job Category
AND (@CategoryId = '0' OR ts.CategoryID in (select Item from Split_fn(@CategoryId,',') ))
-- Contact Id (always filter on this, enough security?!)
AND ts.BuildingID IN (SELECT distinct b.BuildingId
FROM
wsm_ContactSite s
INNER JOIN
wsm_Contact c ON c.ContactID = s.ContactID
INNER JOIN
wsm_Ref_Buildings b ON b.SiteId = s.SiteID
WHERE
c.ContactID = @ContactUserId)
AND wsm_Contact.FloorID IN (SELECT t.FloorID
FROM wsm_Contact_Tenancy t
WHERE t.ContactID = @ContactUserId)
AND wsm_Contact.OCCPSTAT NOT IN ('I', 'P')
AND (@vJobType IS NULL OR ts.JobType in (select Item from Split_fn(@vJobType,',')))
AND (ts.Created between @CreatedFrom and DATEADD(DD,1,@CreatedTo))
ORDER BY
JobID
统计信息:
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
Table 'TSP_CAT_Category'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'wsm_Contact_Tenancy'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'wsm_Contact'. Scan count 2, logical reads 3822, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'wsm_ContactSite'. Scan count 1, logical reads 5, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'wsm_Ref_Buildings'. Scan count 3, logical reads 2811, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 2, logical reads 341364, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#AFEC4F2F'. Scan count 2, logical reads 524444, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'TSP_TSR_Job'. Scan count 3, logical reads 58210, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'wsm_Contact_User'. Scan count 2, logical reads 2300, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'TSP_TSR_JobStatus'. Scan count 2, logical reads 650, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '1159564537'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#BB5E01DB'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#BA69DDA2'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#B1D497A1'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table '#B0E07368'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 8391 ms, elapsed time = 5792 ms.
SQL Server Execution Times:
CPU time = 8391 ms, elapsed time = 5793 ms.
答案 0 :(得分:1)
wsm_Ref_Buildings
添加聚簇索引IN
变成EXISTS
OPTION RECOMPILE
,因为您真的需要所有这些OR
Split_fn
主体(有更干净的此类代码示例以及SQL SERVER SPLIT_STRING函数附带的代码),
确保Split_fn
是DETERMINISTIC
(需要WITH SCHEMABINDING
选项)DISTINCT
s TSP_CAT_Category
表)DISTINCT
子查询中的 IN
s只做毫无意义的多余排序,这对查询逻辑或输出没有影响。最顶端的DISTINCT
修复(或仍然不做)设计不良的查询:重复的行(如果有)是由错误定义的连接产生的,必须将其固定(例如OUTER APPLY (SELECT TOP 1...)
)。
upd
Exists
示例:
WHERE ts.CategoryID in (select Item from Split_fn(@CategoryId,',') )
->>
WHERE EXISTS (select 1 from Split_fn(@CategoryId,',') s WHERE s.Item = ts.CategoryID)
答案 1 :(得分:0)
Ivan Starostin有很多建议,在此我不再赘述,但我想请您考虑一下为什么您首先觉得需要使用“独特”。
select distinct
使用ADDS进行查询需要花费大量时间和精力,这不是“广泛查询”(多列查询)的好方法,特别是在查询涉及多个联接表的情况下。虽然将表连接在一起是司空见惯且必不可少的,但不要忘记联接通常会产生将行数相乘的效果。因此,如果有太多的行,则在完全依靠select distinct
作为灵丹妙药之前重新考虑联接。
例如,这是否需要“与众不同”?
SELECT
ts.JobID
, ts.Contact
, ts.ContactEmail
, ts.Created
, ts.CreatedBy
, ts.JobType
FROM dbo.TSP_TSR_Job ts
WHERE (ts.Created BETWEEN @CreatedFrom AND DATEADD(DD, 1, @CreatedTo))
AND (@JobID = 0 OR ts.JobID = @JobId)
AND (@TenancyId = '0' OR ts.TenancyId IN (
SELECT
Item
FROM Split_fn(@TenancyID, ',')
)
)
如果(我怀疑)不需要“与众不同”,则将其用作子查询,然后再添加其余表。您也许还可以合并用于类别和状态的查找表,而无需添加其他行,例如
SELECT
ts.JobID
, ts.Contact
, ts.ContactEmail
, ts.Created
, ts.CreatedBy
, ts.JobType
, dbo.TSP_CAT_Category.Category
, dbo.TSP_TSR_JobStatus.JobStatus
FROM dbo.TSP_TSR_Job ts
LEFT OUTER JOIN dbo.TSP_TSR_JobStatus ON ts.JobStatusID = dbo.TSP_TSR_JobStatus.JobStatusID
LEFT OUTER JOIN dbo.TSP_CAT_Category ON ts.CategoryID = dbo.TSP_CAT_Category.CategoryID
WHERE (ts.Created BETWEEN @CreatedFrom AND DATEADD(DD, 1, @CreatedTo))
AND (@JobID = 0 OR ts.JobID = @JobId)
AND (@TenancyId = '0' OR ts.TenancyId IN (
SELECT
Item
FROM Split_fn(@TenancyID, ',')
)
)
-- Job Category
AND (@CategoryId = '0'
OR ts.CategoryID IN (
SELECT
Item
FROM Split_fn(@CategoryId, ',')
)
)
AND (@vJobType IS NULL
OR ts.JobType IN (
SELECT
Item
FROM Split_fn(@vJobType, ',')
)
)
如果不需要“ distinct”,则将其用作子查询(“派生表”或“公共表表达式”),然后尝试将每个其他联接一个接一个地添加(即添加联接,以及相关位置子句过滤器,并为此表添加所选的列)。然后,如果您在该额外联接之后开始在结果中看到不需要的重复,则知道重复来自何处。您可能需要使用与该表完全不同的方法来解决此问题(例如,加入使用row_number()来仅获取“最新”联系人的子查询)。
答案 2 :(得分:-1)
您可以在查询中为wsm_Contact,TSP_TSR_JobStatus,TSP_CAT_Category,wsm_Contact_User以及它们的别名使用别名