2012-01-21 2 views
0

87 열과 53,000 행이있는 tblStkMst2 테이블이 있습니다. 다음 쿼리를 실행하면 83-96 밀리 초 (Core2 Duo, 2.8GHz, 2GB RAM)가 소요됩니다. 그러나 별개의 키워드를 사용하면 1086 ~ 1103 밀리 초 (1 초 이상)가 소요됩니다. 그것은 정말로 비싸다. 53,000 행의 데이터에 중복 제거 알고리즘을 적용하면 1 초가 걸리지 않습니다.DISTINCT SQL Server 2005 성능 문제

SQL Server 2005에서 실행 시간을 향상시키는 다른 방법이 있습니까?

declare @monthOnly int     set @monthOnly = 12 
declare @yearOnly int     set @yearOnly = 2011 

SELECT --(distinct)-- 

tblSModelMst.SMNo as [ModelID] 
,tblSModelMst.Vehicle as [ModelName] 

FROM tblStkMst2 

INNER JOIN tblDCDetail ON tblStkMst2.DCNo = tblDCDetail.DCNo AND tblDCDetail.Refund=0 
INNER JOIN tblSModelMst ON tblStkMst2.SMno = tblSModelMst.SMNo 
INNER JOIN tblBuyerMst ON tblDCDetail.BNo = tblBuyerMst.BNo 
LEFT OUTER JOIN tblSModelSegment ON tblSModelMst.SMSeg = tblSModelSegment.ID 
left outer JOIN dbo.tblProdManager as pd ON pd.PMID = tblBuyerMst.PMId 


WHERE (pd.Active = 1) AND ((tblStkMst2.ISSFlg = 1) or (tblStkMst2.IsBooked = 1)) 
    AND (MONTH(tblStkMst2.SIssDate) = @monthOnly) AND (YEAR(tblStkMst2.SIssDate) = @yearOnly) 
+0

조정 권고자를 사용하고 예상 실행 계획을 표시하려고 시도 했습니까? 이것들은 당신이 시간을 어디에서 찾고 있는지를 찾는데 도움을 줄 것입니다. 또한 모든 기본 키 및 외래 키 열에 대한 인덱스가 있습니까? –

+1

"DISTINCT"버전 이상 실행 계획을 보여주십시오. –

+0

@Abidul Islam - 당신의 지속적인 도움을 원하면 사람들에게 반응해야합니다. –

답변

0

몇 가지가 있습니다.

1-DISTINCT

이 사용하지 마십시오 - 다른 JOIN 키를 TblSModelMst(SMNo) INCLUDE (Vehicle)에 인덱스를 작성하고.

왜 중복을 가져오고 먼저 처리해야하는지 알아야합니다.JOIN ed 테이블 중 하나 이상에서 일치하는 추가 행이있을 가능성이 큽니다.

DISTINCT는 장소가 있지만 크게 알려지지 않은 데이터 문제에 남용이며, 그것은 당신이에서 내려 필터링 된 행의 수가 많은 특히, 매우 고가의 운영자입니다.

보다 완벽한 대답을 얻으려면 데이터 구조와 달성하려는 것을 설명해야합니다.

1

SQL Server는 최악의 경우 실행을 피하기 위해 최적화합니다. 이것은 해쉬 정렬을 통해 디스크 정렬을 선호하는 것처럼 차선책의 알고리즘을 선호하도록 유도 할 수 있습니다.

제한된 수의 고유 한 값의 경우 해시 정렬이 distinct 작업을 실행하는 가장 빠른 방법입니다. 해시 정렬은 실행 속도를 위해 메모리를 교환합니다. 그러나 값이 많으면 해시가 너무 커서 메모리에 저장할 수 없기 때문에 해시 정렬이 중단됩니다. 따라서 해시가 메모리에 들어갈 수 있음을 SQL Server에 알리는 방법이 필요합니다. 그것은 많은 경우에 더 나은 알고리즘을 선택할 수 있도록

declare @t (ModelID int, ModelName varchar(50)) 
insert @t (ModelID, ModelName) select ...your original query here... 
select distinct ModelID, ModelName from @t 

SQL Server가 임시 테이블의 크기를 알 : 그 작업을 수행하는

한 가지 가능한 방법은 임시 테이블을 사용하는 것입니다.

+1

이것에 대한 모든 문서? –

4

DISTINCT가 매우 비싸지 않습니다 (이것은 53000 개의 행으로 작음). DISTINCT를 추가 할 때 SQL Server가 완전히 다른 쿼리 계획을 선택하기 때문에 상당한 성능 차이가 나타납니다. 쿼리 계획을 보지 않고도 무슨 일이 일어나고 있는지보기가 어렵습니다.

쿼리에 몇 가지 사항이 있지만 성능을 크게 향상시킬 수있는 방법이 있습니다.

(1) 피 위치를 열 변환하기 위해 필요한이 같은 조항 : 당신이 그것을 사용할 수 없게됩니다 SIssDate 열 SQL Server의 인덱스가있는 경우 그 가능성이 것 (

AND (MONTH(tblStkMst2.SIssDate) = @monthOnly) AND (YEAR(tblStkMst2.SIssDate) = @yearOnly) 

을 다른 인덱스를 사용할 수 없다고 의심되는 테이블 스캔을 수행하십시오.)

AND (tblStkMst2.SIssDate between @minDate and @maxDate); 

: 당신이 SIssDate 지수를 활용하려면 당신이 시도하고 최소 및 최대 날짜에 @ monthOnly/@ yearonly 매개 변수를 변환하고 쿼리에서 다음을 사용하는 경우

, 그것은 더 당신이 테이블에 (클러스터 된 인덱스) 대리 기본 키가있는 경우

SELECT @minId=MIN(tblStkMst2_id), @maxId=(tblStkMst2_id) 
FROM 
tblStkMst2 WHERE tblStkMsg2.SIssDate between @minDate and @maxDate; 

이 있어야합니다, 당신이 당신의 쿼리 (tblStkMst2_id라고 당신의 대리 기본 키를 가정)를 실행하기 전에이 작업을 수행하는 데 유용 할 수 있습니다 SQL 서버가 ta를 보지 않아도되므로 매우 빠릅니다. ble (SIssDate 비 클러스터형 인덱스와 tblStkMst2_id 클러스터형 인덱스에서만). 클러스터 된 인덱스가 훨씬 빠르게 순차적으로 할 수있을 것입니다 DB로 클러스터되지 않은 인덱스를 사용하는 것보다 사용

AND (tblStkMst2.tblStkMst2_id BETWEEN @minId and @maxId); 

:

그런 다음 당신은 당신의 주 (대신 날짜 검사) 쿼리에서이 작업을 수행 할 수 있습니다 이러한 레코드에 액세스하십시오 (클러스터되지 않은 인덱스 리디렉션을 거치지 않고).

(2) DISTINCT (또는 GROUP BY)를 수행 할 때까지 tblStkMst2에 대한 조인을 지연시킵니다. DISTINCT (GROUP BY)의 항목 수가 적을수록 좋습니다.

+0

+1'MONTH()'와'YEAR()'호출을 제거하여 쿼리를 변경하면 성능에 큰 영향을 미칠 것이라고 생각합니다. –