2011-04-06 230 views
3

我有一个视图名称“vw_AllJobsWithRecruiter”。查询优化SQL Server 2008

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. 我该如何缩短执行时间?

非常感谢您的关注。

+0

子句TOP的用途是什么(SELECT COUNT(iJobID_PK)FROM dbo.tbUS_Jobs)?这很奇怪,可能无用。如果你需要有iJobID_PK不为空的行,那么WHERE子句更合适。 – Skrol29 2011-04-06 11:53:10

+0

与出使用子句TOP(SELECT COUNT(iJobID_PK)FROM dbo.tbUS_Jobs),我不能使用视图中的顺序。 – 2011-04-06 11:54:41

+0

@ Skrol29 TOP(..)构造等于'SELECT TOP 100%'并指示SQL Server遵循'ORDER BY'。没有TOP会忽略订单。 – 2011-04-06 11:55:25

回答

4

第一个查询只针对返回的行调用dbo.ufn_RecruiterCompanyName(),它对存储的值进行过滤。对于第二个查询,SQL Server需要为所有行调用ufn。根据功能的不同,这可能会导致延迟。

入住这在查询分析器,并尽量避免第二查询^^

考虑看看自定义功能,我建议重写该视图使用连接表后。在这些函数中进行查找时,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 
+0

+1 - 我认为函数调用是问题。 – JNK 2011-04-06 11:53:10

+0

是的你是对的。 dbo.ufn_RecruiterCompanyName()花费很多时间。 – 2011-04-06 12:19:53

+0

@Arindam - 你能发布那个函数的代码吗?或者,是否可以在使用'INNER JOIN'或其他过滤器运行函数之前预先过滤结果? – JNK 2011-04-06 12:22:48

1

的问题是你的嵌套函数调用。

您在WHERE条款中调用ufn_RecruiterCompanyName,尽管是间接的。

这意思是,你的WHERE条款是非Sargable,并且必须运行功能每一行

该函数也调用ufn_GetParentRecruiterID。既然这是在第一个函数中的WHERE子句中,并且也是非Sargable,那么您基本上在您的表中每行执行两次表扫描。

将函数调用替换为JOIN,您将看到性能的巨大提升。

+0

是的,这是主要问题。我正在尝试通过加入。非常感谢。 – 2011-04-06 12:59:47