繁体   English   中英

查询调优SQL Server 2008

[英]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 

我的问题是

  1. 为什么要花这么多时间来执行?
  2. 如何减少执行时间?

非常感谢您的关注。

第一个查询仅对返回的行调用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM