2010-01-05 2 views
0

편집 : 사용하여 SQL Server 2005최적화 SQL 쿼리는 많은 열이 존재하는 절

나는 레거시 데이터베이스에서 행이 이미으로 가져온 여부를 확인하는 쿼리가 새 데이터베이스를 가져오고 이미없는 경우 가져옵니다. 레거시 데이터베이스가 잘못 설계 되었기 때문에 레거시 테이블의 행에 대해 고유 한 ID가 없으므로 휴리스틱을 사용하여 행을 가져 왔는지 여부를 결정해야합니다. (나는 레거시 데이터베이스를 제어 할 권한이 없다.) 새 데이터베이스는 약간 다른 구조를 가지고 있으며, 날짜가 일치하는지, 그룹 번호가 일치하는지 등과 같은 여러 값을 검사해야만 새로운 데이터베이스에 행이 있는지 또는 아니. 그다지 예쁘지는 않지만 인터페이스가있는 레거시 시스템의 나쁜 설계로 인해 선택의 여지가 거의 없습니다.

어쨌든 시스템 사용자는 내가 설계 한 것보다 시스템에서 10 배에서 100 배 더 많은 데이터를 던지기 시작했으며 이제 쿼리가 너무 느리게 실행됩니다. 빨리 할 수있는 방법을 제안 해 주시겠습니까? 다음은 몇 가지 개인 정보 보호를 위해 redadacted 또는 단순화하기로 코드는,하지만 난 내가 중요한 부분 왼쪽 생각 : 스키마, 당신의 첫 번째 단계는 그 하위 쿼리 EXPLAIN이다 생겼는지 알고하지

INSERT INTO [...NewDatabase...] 
SELECT [...Bunch of columns...] 
    FROM [...OldDatabase...] AS t1 
WHERE t1.Printed = 0 
    AND NOT EXISTS(SELECT * 
        FROM [...New Database...] AS s3 
        WHERE year(s3.dtDatePrinted) = 1850 --This allows for re-importing rows marked for reprint 
        AND CAST(t1.[Group] AS int) = CAST(s3.vcGroupNum AS int) 
        AND RTRIM(t1.Subgroup) = s3.vcSubGroupNum 
        AND RTRIM(t1.SSN) = s3.vcPrimarySSN 
        AND RTRIM(t1.FirstName) = s3.vcFirstName 
        AND RTRIM(t1.LastName) = s3.vcLastName 
        AND t1.CaptureDate = s3.dtDateCreated) 
+0

@OMGPonies : 세부 정보 ?? 우리는 더러운 정보가 필요하지 않습니다 !! :-) (죄송합니다 - 내부의 농담 - 그냥 "호의"를 되 돌리는 것을 막을 수 없었습니다 ) –

+1

@marc_s : 그건 내 뻔뻔스럽게 Cheech & Chong에게서 털어 놓은 것입니다 : p –

+0

Whoa stupid of me. 물론 당신은 어떤 데이터베이스인지 알아야합니다. 그것은 SQL Server 2005입니다. 왜냐하면 ... 우리는 색인에 알레르기가 있기 때문에 칼럼에 색인이 없습니다. 또는 우리는 그들이 당신의 영혼을 훔쳐 간다고 생각합니다. 또는 뭔가; 나는 왜 그런지 모르지만 나는 그들에게 의존하지 말라고 들었다. – Dennis

답변

2

합니다. 그것은 데이터베이스가 그 시간을 씹고있는 곳을 보여 주어야합니다. 인덱스가 없으면 여러 개의 전체 테이블 스캔을 수행 할 가능성이 있습니다. 짐작해야만한다면, 나는 이미 변환 된 것을 제거 할 것이기 때문에 t1.printeds3.dtDatePrinted이 색인을 생성하는 가장 중요한 두 가지라고 말하고 싶습니다.

또한 계산해야하는 모든 항목은 데이터베이스가 색인을 사용하지 못하게 할 수도 있습니다. 예를 들어, RTRIMCAST에 대한 호출입니다. 이는 새 데이터베이스에 더러운 데이터가 있음을 나타냅니다. 영구적으로 제거하고 t1.group을 올바른 유형으로 변경하는 방법을 살펴보십시오.

year(s3.dtDatePrinted) = 1850s3.dtDatePrinted에 대한 색인을 사용하지 않도록 최적화 프로그램을 속일 수도 있습니다 (EXPLAIN이 알려야 함). 이것은 행이 이미 변환되었는지 확인하기 위해 설정 한 플래그로 표시되므로 특정 날짜 (예 : 1850-01-01 00:00:00)로 설정하고 일치하는 항목을 지정하십시오 (예 : s3.dtDatePrinted = "1850-01-01 00:00:00").) 이제는 간단한 색인 조회입니다.

비교를 간단하게 만드는 것도 도움이됩니다. 본질적으로 여기에있는 것은 t1과 s3 사이의 1 대 1 관계입니다 (t1이 새 테이블의 실제 이름 인 경우 더 자세한 설명이 필요합니다). 따라서 s3의 각 비트를 t1에 매칭하는 대신 t1에 해당 s3 행의 기본 키를 참조하는 열을 제공하십시오. 그런 다음 한 가지만 확인하면됩니다. t1을 변경할 수 없다면 세 번째 테이블을 사용하여 t1에서 s3으로의 매핑을 추적 할 수 있습니다.

일단 그렇게하면, t3에없는 s3의 행을 찾기위한 조인 만하면됩니다.

SELECT s3.* 
FROM s3 
LEFT JOIN t1 ON t1.s3 = s3.id -- or whatever s3's primary key is 
WHERE t1.s3 IS NULL 
+0

감사합니다. 레거시 시스템이 언젠가 교체 될 것이므로 더 이상 불만을 품지 않기로 결심했습니다. 그러나 더 나은 최신 가져 오기를 설계 할 수 있도록 해답을 얻는 것이 좋습니다. 거기에 자리 잡고 있습니다. 쿼리 계획은 지적한 핫스팟에 대부분의 시간대 검색을 보내고 있음을 나타냅니다. 특히 나를 신비화시킨 한 가지는 year (s3.dtDatePrinted) = 1850; 나는 그것이 쿼리 계획을 믿지 않았다는 것을 확신하는 방법이었습니다. 저를 위해 저것을 설명하기를위한 감사합니다. – Dennis

+0

@Dennis 오신 것을 환영합니다! 다행 이었기 때문에 다행이었습니다. – Schwern

0

이 교체한다 :이

년 (s3.dtDatePrinted) = 1,850

을 :

s3.dtDatePrinted> = '1850년 1월 1일'및 s3.dtDatePrinted < '1851-01-01'

이 경우 dtDatePrinted MAYBE에 색인이있는 경우 최적화 프로그램은 범위 색인 스캔을 사용할 수 있습니다.

하지만 RTRIM을 피해야한다는 이전 포스터에 동의합니다.하나의 아이디어는 s3에서 트리밍되지 않은 (원래) 값을 유지하거나 트리밍되지 않은 값을 트리밍 된 (새로운) 값으로 매핑하는 중간 테이블을 만드는 것입니다. 또는 구체화 된보기 작성. 그러나이 모든 작업은 적절한 색인 없이는 쓸모가 없습니다.