EXCEPT 연산자의 알고리즘은 무엇입니까?


10

Except 연산자가 SQL Server에서 다루는 방식에 대한 내부 알고리즘은 무엇입니까 ? 내부적으로 각 행의 해시를 가져 와서 비교합니까?

David Lozinksi는 연구를 수행했습니다. SQL : 아직 존재하지 않는 새 레코드를 삽입하는 가장 빠른 방법 그는 예외 문이 많은 행에서 가장 빠릅니다. 아래의 결과와 밀접한 관련이 있습니다.

가정 : 왼쪽 조인은 1 열만 비교하기 때문에 가장 빠를 것이라고 생각합니다. 모든 열을 비교해야하기 때문에 가장 오래 걸립니다.
이 결과로 이제 우리의 생각은 자동적으로 그리고 내부적으로 각 행의 해시를 취합니까? 실행 계획 제외를 보았고 일부 해시를 사용합니다.

배경 : 우리 팀은 두 개의 힙 테이블을 비교하고있었습니다. 표 A 표 B에없는 행이 표 B에 삽입되었습니다.

레거시 텍스트 파일 시스템의 힙 테이블에는 기본 키 / guids / identifier가 없습니다. 일부 테이블에는 중복 행이 있으므로 각 행의 해시를 찾아 중복을 제거하고 기본 키 식별자를 만들었습니다.

1) 먼저 (해시 열)을 제외하고 except 문을 실행했습니다.

select * from TableA
Except
Select * from TableB,

2) 그런 다음 HashRowId의 두 테이블 간 왼쪽 조인 비교를 실행했습니다.

select * 
FROM dbo.TableA A
left join dbo.TableB B
    on A.RowHash =  B.RowHash
where B.Hash is null

놀랍게도 Except Statement Insert가 가장 빠릅니다.

결과는 David Lozinksi의 테스트 결과와 거의 비슷합니다.

여기에 이미지 설명을 입력하십시오


답변:


10

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특별한 내부 해싱 비교로 이어지는 특별한 것은 없습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.