Except 연산자가 SQL Server에서 다루는 방식에 대한 내부 알고리즘은 무엇입니까?
에 대한 특별한 내부 알고리즘이 있다고는 말할 수 없습니다 EXCEPT
. 의 경우 A EXCEPT B
엔진은 A에서 구별되는 (필요한 경우) 튜플을 가져와 B에서 일치하는 행을 뺍니다. 특별한 쿼리 계획 연산자가 없습니다. 구별 및 빼기는 정렬 또는 조인으로 표시되는 일반적인 연산자를 통해 구현됩니다. 중첩 루프 조인, 병합 조인 및 해시 조인이 모두 지원됩니다. 이를 보여주기 위해 1,500 만 개의 행을 한 쌍의 힙에 넣습니다.
DROP TABLE IF EXISTS dbo.TABLE_1;
CREATE TABLE dbo.TABLE_1 (
COL1 BIGINT NULL,
COL2 BIGINT NULL
);
INSERT INTO dbo.TABLE_1 WITH (TABLOCK)
SELECT TOP (15000000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), NULL
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
OPTION (MAXDOP 1);
DROP TABLE IF EXISTS dbo.TABLE_2;
CREATE TABLE dbo.TABLE_2 (
COL1 BIGINT NULL,
COL2 BIGINT NULL
);
INSERT INTO dbo.TABLE_2 WITH (TABLOCK)
SELECT TOP (15000000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), NULL
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
OPTION (MAXDOP 1);
옵티마이 저는 정렬 및 결합을 구현하는 방법에 대한 일반적인 비용 기반 결정을 내립니다. 두 개의 힙으로 예상대로 해시 조인을 얻습니다. 인덱스를 추가하거나 두 테이블의 데이터를 변경하여 다른 조인 유형을 자연스럽게 볼 수 있습니다. 아래에서는 설명을 위해 힌트로 병합 및 루프 조인을 강제합니다.
내부적으로 각 행의 해시를 가져 와서 비교합니까?
아니요. 다른 조인으로 구현됩니다. 한 가지 차이점은 NULL이 동일하게 취급된다는 것입니다. 이것은 실행 계획에서 볼 수있는 특수한 유형의 비교입니다 <Compare CompareOp="IS">
. 그러나 EXCEPT
키워드가 포함되지 않은 T-SQL을 사용하여 동일한 계획을 얻을 수 있습니다 . 예를 들어 다음은 EXCEPT
해시 조인을 사용하는 쿼리 와 정확히 동일한 쿼리 계획입니다 .
SELECT t1.*
FROM
(
SELECT DISTINCT COL1, COL2
FROM dbo.TABLE_1
) t1
WHERE NOT EXISTS (
SELECT 1
FROM dbo.TABLE_2 t2
WHERE (t1.COL1 = t2.COL1 OR (t1.COL1 IS NULL AND t2.COL1 IS NULL))
AND (t1.COL2 = t2.COL2 OR (t1.COL2 IS NULL AND t2.COL2 IS NULL))
);
실행 계획의 XML을 비교하면 별칭과 그와 관련된 것의 피상적 차이 만 드러납니다. 해시 조인의 프로브 잔차는 행 비교를 수행합니다. 두 쿼리 모두 동일합니다.
여전히 의심 스러우면 가능한 가장 높은 샘플 속도로 PerfView 를 실행 하여 쿼리와 EXCEPT
쿼리가없는 호출 스택을 얻 습니다. 결과는 나란히 있습니다 :
실제 차이는 없습니다. 계획의 해시 일치로 인해 해시를 참조하는 호출 스택이 존재합니다. 자연스러운 병합 조인을 얻기 위해 인덱스를 추가하면 호출 스택에 해싱에 대한 참조가 표시되지 않습니다.
발생하는 해싱은 해시 일치 연산자의 구현으로 인한 것입니다. EXCEPT
특별한 내부 해싱 비교로 이어지는 특별한 것은 없습니다 .