[英]Query tuning SQL Server 2008
我有一个视图名称“vw_AllJobsWithRecruiter”。
ALTER VIEW dbo.vw_AllJobsWithRecruiter
AS
SELECT TOP(SELECT COUNT(iJobID_PK) FROM dbo.tbUS_Jobs)
iJobId_PK AS JobId,
dbo.ufn_JobStatus(iJobId_PK) AS JobStatus,
dbo.ufn_RecruiterCompanyName(iJobId_PK) AS CompanyName,
sOther AS OtherCompanyName
FROM dbo.tbUS_Jobs
WHERE bDraft = 0
ORDER BY dtPostedDate DESC
此视图仅包含3278行。
如果我执行以下查询:
SELECT * FROM vw_AllJobsWithRecruiter
WHERE OtherCompanyName LIKE '%Microsoft INC%'
执行时间不到一秒。
现在我的问题是:
如果我使用下面的查询查询:
SELECT * FROM vw_AllJobsWithRecruiter
WHERE CompanyName LIKE '%Microsoft INC%'
OR OtherCompanyName LIKE '%Microsoft INC%'
它需要30秒才能执行,并且从前端开始抛出超时错误。 功能在这里:
CREATE Function [dbo].[ufn_RecruiterCompanyName] (@JobId bigint)
RETURNS nvarchar(200)
AS
BEGIN
DECLARE @ResultVar nvarchar(200)
DECLARE @RecruiterId bigint
select @RecruiterId = iRecruiterId_FK from dbo.tbUS_Jobs with (Nolock)
where iJobId_PK = @JobId;
Select @ResultVar = sCompanyName from dbo.tbUS_RecruiterCompanyInfo with (Nolock)
where iRecruiterId_FK = dbo.ufn_GetParentRecruiterID(@RecruiterId)
return isnull(@ResultVar,'')
END
另一个功能
CREATE Function [dbo].[ufn_GetParentRecruiterID](@RecruiterId bigint)
returns bigint
as
begin
declare @ParentRecruiterId bigint
SELECT @ParentRecruiterId = iParentId FROM dbo.tbUS_Recruiter with (Nolock)
WHERE iRecruiterId_PK = @RecruiterId
IF(@ParentRecruiterId = 0)
SET @ParentRecruiterId = @RecruiterId
RETURN @ParentRecruiterId
end
我的问题是
- 为什么要花这么多时间来执行?
- 如何减少执行时间?
非常感谢您的关注。
第一个查询仅对返回的行调用dbo.ufn_RecruiterCompanyName()
,它会对存储的值进行过滤。 对于第二个Query,SQL Server需要为所有行调用ufn。 根据功能,这可能会导致延迟。
在查询分析器中检查这一点,并尝试避免第二个查询^^
看一下自定义函数后,我建议使用连接表重写View。 在这些函数中执行查找时,SQL Server会为它接触或传递的每一行调用它们。 使用LEFT JOIN
允许服务器更快地使用索引和密钥,并且应该在不到一秒的时间内提供数据。
如果没有所有自定义函数和所有表的定义,我不能给你一个新视图的示例,但它应该看起来像这样:
SELECT
jobs.Jobid,
jobstatus.Jobstatus,
recruiter.Company
FROM jobs
LEFT JOIN jobstatus ON jobs.Jobid = jobstatus.Jobid
LEFT JOIN recruiter ON jobs.Recruiterid = recruiter.Recruiterid
问题是你的嵌套函数调用。
您在WHERE
子句中调用ufn_RecruiterCompanyName
,虽然是间接的。
这意味着,您的WHERE
子句是非Sargable ,并且必须为每一行运行该函数。
该函数还调用ufn_GetParentRecruiterID
。 由于这是在第一个函数中的WHERE
子句中,也是非Sargable,因此您基本上在表中每行进行两次表扫描。
用JOIN
替换函数调用,您将看到性能的巨大提升。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.