2011-04-06 5 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%' 

그것은 실행할 초 미만 복용 : 나는 아래의 쿼리를 실행하면

.

이제 내 문제는 다음과 같습니다

내가 쿼리 아래의 쿼리를 사용하는 경우 : 그것은 실행하는 30 초 복용하고 프론트 엔드에서 시간 초과 오류를 던지고있다

SELECT * FROM vw_AllJobsWithRecruiter 
WHERE CompanyName LIKE '%Microsoft INC%' 
     OR OtherCompanyName LIKE '%Microsoft INC%' 

합니다. 기능은 여기에 있습니다 :

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

+0

을 사용하여 TOP (SELECT COUNT (iJobID_PK) FROM dbo.tbUS_Jobs) 절을 사용하면보기에서 주문을 사용할 수 없습니다. –

+0

@ Skrol29 그 TOP (..) Construct는'SELECT TOP 100 %'와 같고 SQL 서버가'ORDER BY'를 따르도록 지시합니다. TOP가 없으면 주문을 무시합니다. –

답변

4

첫 번째 쿼리는 반환 된 행에 대해서만 dbo.ufn_RecruiterCompanyName()만을 호출하며 저장된 값으로 필터링합니다. 두 번째 쿼리의 경우 SQL Server는 모든 행에 대해 ufn을 호출해야합니다. 기능에 따라 지연이 발생할 수 있습니다.

쿼리 분석기에서

확인이, 내가보기 조인 된 테이블을 사용하여 재 작성하는 것을 권장합니다 사용자 지정 함수를 한 번 봐 복용 후 두 번째 쿼리 ^^

을 피하려고합니다. 이러한 함수에서 조회를 수행 할 때 SQL Server는 접촉하거나 전달하는 모든 Row에 대해 호출합니다. LEFT JOIN을 사용하면 서버가 색인 및 키를 더 빨리 사용할 수 있으며 1 초 이내에 데이터를 제공해야합니다. 사용자 정의의 모든 기능 및 모든 테이블의 정의없이

, 난 당신에게 그 새보기의 예를 줄 수는 없지만,이 같은 비트가 보일 것입니다 :

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

+0

예, 맞습니다. dbo.ufn_RecruiterCompanyName()이 많은 시간을들입니다. –

+0

@Arindam - 해당 기능의 코드를 게시 할 수 있습니까? 또는 'INNER JOIN'또는 다른 필터를 사용하여 함수를 실행하기 전에 결과를 사전 필터링 할 수 있습니까? – JNK

1

문제가 중첩되어 함수 호출.

귀하는 WHERE 조항에 간접적이긴하지만 ufn_RecruiterCompanyName으로 전화를 걸고 있습니다. 이 의미

WHERE 절은 비 Sargable이며, 모든 행 위해 해당 기능을 실행해야합니다.

해당 함수는 ufn_GetParentRecruiterID도 호출합니다.그것이 첫 번째 함수 내에서 WHERE 절에 있고 Sargable이 아니기 때문에 기본적으로 테이블의 행당 두 개의 테이블 스캔을 수행합니다.

함수 호출을 JOIN으로 바꾸면 성능이 크게 향상됩니다.

+0

예, 이것이 주요한 문제입니다. 나는 Join으로 해보려고합니다. 고마워. –