我有一个名字“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
我的问题是
- 为什么要花这么多时间来执行?
- 如何缩短执行时间?
醇>
非常感谢您的关注。
答案 0 :(得分:4)
第一个查询仅对返回的行调用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
答案 1 :(得分:1)
问题是你的嵌套函数调用。
您正在ufn_RecruiterCompanyName
条款中调用WHERE
,虽然是间接的。
这意味着,您的WHERE
子句不是Sargable,并且必须为每一行运行该功能。
该函数也调用ufn_GetParentRecruiterID
。由于这是在第一个函数中的WHERE
子句中,也是非Sargable,因此您基本上在表中每行进行两次表扫描。
用JOIN
替换函数调用,您将看到性能的巨大提升。