2012-05-10 2 views
0

SQL 2000을 사용하고 있습니다. 복잡한 기준에 따라 원하지 않는 복제본을 모두 제거 할 수있는 지점을 얻었지만 이제는 약 3.5 분이 걸렸을 때 쿼리를 완료하는 데 몇 시간이 걸립니다. 포함 된 사본으로 데이터를 가져옵니다.이 중복 제거 쿼리는 어떻게 최적화 할 수 있습니까?

투명도 : rpt.HostName 또는 rpt.SystemSerialNumber 필드가 다른 경우 중복 rpt.Name 필드가있을 수 있습니다. 또한, 일부 열의 시간 소인이 없어서 네 개의 다른 열의 시간 소인을 기반으로 유지할 항목을 결정해야합니다.

도움을 주시면 대단히 감사하겠습니다. 그 라인을 따라

SELECT 
rpt.[Name], 
rpt.LastAgentExecution, 
rpt.GroupName, 
rpt.PackageName, 
rpt.PackageVersion, 
rpt.ProcedureName, 
rpt.HostName, 
rpt.SystemSerialNumber, 
rpt.JobCreationTime, 
rpt.JobActivationTime, 
rpt.[Job Completion Time] 
FROM DSM_StandardGroupMembersProcedureActivityViewExt rpt 
WHERE 
(
    (
     rpt.GroupName = 'Adobe Acrobat 7 Deploy' 
    OR rpt.GroupName = 'Adobe Acrobat 8 Deploy' 
) 
    AND 
    (
     (rpt.PackageName = 'Adobe Acrobat 7' AND rpt.PackageVersion = '-1.0') 
    OR (rpt.PackageName = 'Adobe Acrobat 8' AND rpt.PackageVersion = '-3.0') 
) 
) 
AND NOT EXISTS 
(
    SELECT * 
    FROM DSM_StandardGroupMembersProcedureActivityViewExt rpt_dupe 
    WHERE 
    (
    (
    rpt.GroupName = 'Adobe Acrobat 7 Deploy' 
     OR rpt.GroupName = 'Adobe Acrobat 8 Deploy' 
    ) 
    AND 
    (
    (rpt.PackageName = 'Adobe Acrobat 7' AND rpt.PackageVersion = '-1.0') 
     OR (rpt.PackageName = 'Adobe Acrobat 8' AND rpt.PackageVersion = '-3.0') 
    ) 
    AND 
    (
     (rpt_dupe.[Name] = rpt.[Name]) 
     AND 
     (
     (rpt_dupe.SystemSerialNumber = rpt.SystemSerialNumber) 
    OR (rpt_dupe.HostName = rpt.HostName) 
    ) 
     AND 
     (
     (rpt_dupe.LastAgentExecution < rpt.LastAgentExecution) 
    OR (rpt_dupe.JobActivationTime  < rpt.JobActivationTime) 
    OR (rpt_dupe.JobCreationTime  < rpt.JobCreationTime) 
    OR (rpt_dupe.[Job Completion Time] < rpt.[Job Completion Time]) 
    ) 
    ) 
) 
) 
+0

실제 실행 계획의 스크린 샷을 게시하십시오 (권장되지 않는 것이 좋음). – usr

+0

바보 같은 코멘트 일지 모르지만 NOT EXISTS 절 대신 duplicate를 제거하기 위해 DISTINCT 키워드를 사용해 보셨습니까? –

+0

Dan, 그의 중복 정의는 쿼리가 반환하는 필드 집합을 기반으로한다고 가정합니다. 합리적인 가정이지만 이것이 반드시 사실 일 수는 없습니다. –

답변

0

이유는없는 절 존재한다.

한 제안은 왼쪽 외부로이를 다시 작성하는 것입니다 가입 :

from <big query> left outer join 
     <dups query> 
     on <all the fields that constitute a match> 
where <dups query>.<some field> is null 

난 안가 존재하는 것으로 나타났습니다 아니라 수시로에서 가난하게 최적화 할 수 있습니다.

또 다른 제안은 더 직접적인 구현이 쿼리를 변경하는 것입니다 :

입니다
with t as (
    SELECT rpt.[Name], rpt.LastAgentExecution, rpt.GroupName, rpt.PackageName, 
      rpt.PackageVersion, rpt.ProcedureName, rpt.HostName, rpt.SystemSerialNumber, 
      rpt.JobCreationTime, rpt.JobActivationTime, rpt.[Job Completion Time] 
    FROM DSM_StandardGroupMembersProcedureActivityViewExt rpt 
    WHERE rpt.GroupName in ('Adobe Acrobat 7 Deploy', 'Adobe Acrobat 8 Deploy') AND 
      ((rpt.PackageName = 'Adobe Acrobat 7' AND rpt.PackageVersion = '-1.0') OR 
      (rpt.PackageName = 'Adobe Acrobat 8' AND rpt.PackageVersion = '-3.0') 
     ) 
) 
select t.* 
from t join 
     (select name, ..., max(id) 
     from t 
     group by name, ... 
    ) tsum 
     on t.id = tsum.id 

, 당신은 구별 할 열에서 테이블을 요약합니다. 행 중 하나를 선택하십시오. 여기서는 각 행을 고유하게 식별하는 "id"필드가 있다고 가정합니다. 이름과 날짜와 같은 필드의 조합을 사용해야 할 수도 있습니다. 이드가 없다면 이것은 더욱 어렵습니다. 최신 버전의 SQL Server에서는 row_number()를 사용할 수 있습니다.

0

시도 :

SELECT t_main.columns 
FROM table as t_main 
LEFT JOIN 
(
SELECT name, MAX(lastAgentExecution)..... FROM table GROUP BY name,serialnumber, hostname 
) 
as t_joinSerial 
ON t_main.name=t_joinSerial.name,lastAgentExecution etc. 
where (t_main.AdobeStuff and t_joinSerial is NULL) 
+0

MAX (lastAgentExecution)가 두 개의 이름을 반환하는 상황을 어떻게 다룰 것인가? 우선 순위 순서대로 MAX (JobActivationTime) 또는 MAX (JobCreationtime) 또는 MAX (JobCompletionTime)? – user1367200

+0

내부 선택에 하나의 특정 레코드가 없어 -하지만 당신은 각 레코드의 각 필드의 최대 값이 있습니다. 하나의 레코드에서 가장 높은 lastAgent를 가지며 다른 레코드에서 가장 높은 jobActivation을 갖는 경우 작동하지 않습니다. 이 접근법은 복잡해질 것입니다. 이것은 자주 작성해야하는 쿼리입니까? 이 테이블에서 추가 필드를 사용하여 하나 이상의 단계에서 문제를 해결할 수 있습니까? BTW. ID 필드가 있습니까? – Johanness

관련 문제