크기가 매우 다른 두 테이블에 대해이 쿼리를 실행 해 보았습니다. #temp는 약 15,000 행이고 Member는 약 70,000,000이며 그중 약 68,000,000에는 ID 307이 없습니다.
SELECT COUNT(*)
FROM #temp
WHERE CAST(individual_id as varchar) NOT IN (
SELECT IndividualID
FROM Member m
INNER JOIN Person p ON p.PersonID = m.PersonID
WHERE CompanyID <> 307)
이 쿼리는 내가 그것을 죽이고 다른 것을 시도하기 전에 18 시간 동안 실행되었습니다.
SELECT IndividualID
INTO #source
FROM Member m
INNER JOIN Person p ON p.PersonID = m.PersonID
WHERE CompanyID <> 307
SELECT COUNT(*)
FROM #temp
WHERE CAST(individual_id AS VARCHAR) NOT IN (
SELECT IndividualID
FROM #source)
그리고 이것은 나에게 결과를주기 전에 1 초도 채 안되는 시간 동안 실행되었습니다.
나는 이것에 꽤 놀랐습니다. 저는 SQL 전문가가 아닌 중간 계층 개발자이며 내부에서 진행되는 작업에 대한 이해가 약간 모호하지만 첫 번째 시도의 하위 쿼리가 똑같은 코드이기 때문에 가정했을 것입니다. 두 번째 시도에서와 똑같은 데이터를 요청하면 대략적으로 동일합니다.
그러나 그것은 분명히 잘못된 것입니다. SQL Server가 수행하려는 작업을 확인하기 위해 원래 쿼리에 대한 실행 계획을 볼 수 없습니다. 그렇다면 누군가 임시 테이블로 데이터를 분할하는 것이 왜 그렇게 더 빠른지 친절하게 설명 할 수 있습니까?
편집 : 테이블 스키마 및 인덱스
#temp
표는 두 개의 열이 있습니다, Individual_ID int
그리고Source_Code varchar(50)
Member
그리고 Person
더 복잡하다. 각각 29 개와 13 개 열이 있으므로 전체를 모두 게시하고 싶지는 않습니다. PersonID
int이고 Person의 PK이고 Member의 FK입니다. IndividualID
은 Person의 열입니다. 이것은 작성된 쿼리에서 명확하지 않습니다.
질문하기 전에 LEFT JOIN
대신 사용을 시도했습니다 NOT IN
. 두 번째 쿼리의 성능은 눈에 띄게 다르지 않았습니다. 둘 다 1 초 미만이었습니다. 첫 번째 쿼리에서 중단하기 전에 한 시간 동안 실행되도록 두었습니다. 이는 큰 차이가 없을 것이라고 가정합니다.
또한 원본 테이블과 마찬가지로 #source에 인덱스를 추가 했으므로 성능 영향이 동일해야합니다.
첫째, 쿼리에 실제로 튀어 나온 두 개의 가짜가 있습니다. 로 변환 varchar()
중이지만 길이 인수를 포함하지 않았습니다. 이것은 허용되어서는 안됩니다! 기본 길이는 컨텍스트에 따라 다르며 명시 적이어야합니다.
둘째, 서로 다른 테이블에서 두 개의 키를 일치시키고 있으며 겉보기에는 서로 다른 유형을 가지고 있습니다. 외래 키 참조는 항상 동일한 유형을 가져야합니다. 이것은 성능에 매우 큰 영향을 미칠 수 있습니다. 수백만 개의 행이있는 테이블을 처리하는 경우 데이터 구조에주의를 기울여야합니다.
성능 차이를 이해하려면 실행 계획을 이해해야합니다. 두 쿼리는 매우 다른 실행 계획을 가지고 있습니다. 내 (교육받은) 추측은 첫 번째 버전 버전이 중첩 루프 조인 알고리즘을 사용하고 있다는 것입니다. 두 번째 버전은 더 정교한 알고리즘을 사용합니다. 귀하의 경우 이것은 SQL Server가 테이블에 대한 통계를 유지하는 기능 때문일 것입니다. 따라서 중간 결과를 인스턴스화하면 실제로 최적화 프로그램이 더 나은 쿼리 계획을 생성하는 데 도움이됩니다.
이 논리를 작성하는 가장 좋은 방법에 대한 주제가 많이 조사되었습니다. 여기 에 Aaron Bertrand의 주제에 대한 아주 좋은 토론이 있습니다.
not exists
이 경우 에 대한 선호도에 대해 Aaron과 동의합니다 .
SELECT COUNT(*)
FROM #temp t
WHERE NOT EXISTS (SELECT 1
FROM Member m JOIN
Person p
ON p.PersonID = m.PersonID
WHERE MemberID <> 307 and individual_id = t. individual_id
);
그러나,이 특별한 경우에 이것이 더 나은 성능을 가질 지 모르겠습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다