이름이 동일하고 유형이 지정된 색인화 된 키 열이있는 두 개의 테이블이 있습니다. 그들 중 하나는 고유 한 클러스터형 인덱스를 가지고 있고 다른 하나는 고유하지 않은 인덱스를 가지고 있습니다.
테스트 설정
현실적인 통계를 포함한 설정 스크립트 :
DROP TABLE IF EXISTS #left;
DROP TABLE IF EXISTS #right;
CREATE TABLE #left (
a char(4) NOT NULL,
b char(2) NOT NULL,
c varchar(13) NOT NULL,
d bit NOT NULL,
e char(4) NOT NULL,
f char(25) NULL,
g char(25) NOT NULL,
h char(25) NULL
--- and a few other columns
);
CREATE UNIQUE CLUSTERED INDEX IX ON #left (a, b, c, d, e, f, g, h)
UPDATE STATISTICS #left WITH ROWCOUNT=63800000, PAGECOUNT=186000;
CREATE TABLE #right (
a char(4) NOT NULL,
b char(2) NOT NULL,
c varchar(13) NOT NULL,
d bit NOT NULL,
e char(4) NOT NULL,
f char(25) NULL,
g char(25) NOT NULL,
h char(25) NULL
--- and a few other columns
);
CREATE CLUSTERED INDEX IX ON #right (a, b, c, d, e, f, g, h)
UPDATE STATISTICS #right WITH ROWCOUNT=55700000, PAGECOUNT=128000;
재현
클러스터링 키에서이 두 테이블을 조인하면 일대 다 MERGE 조인이 필요합니다.
SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
l.a=r.a AND
l.b=r.b AND
l.c=r.c AND
l.d=r.d AND
l.e=r.e AND
l.f=r.f AND
l.g=r.g AND
l.h=r.h
WHERE l.a='2018';
이것은 내가 원하는 쿼리 계획입니다.
(경고를 신경 쓰지 말고 가짜 통계와 관련이 있습니다.)
그러나 조인에서 열 순서를 변경하면 다음과 같이됩니다.
SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
l.c=r.c AND -- used to be third
l.a=r.a AND -- used to be first
l.b=r.b AND -- used to be second
l.d=r.d AND
l.e=r.e AND
l.f=r.f AND
l.g=r.g AND
l.h=r.h
WHERE l.a='2018';
...이 발생합니다 :
Sort 연산자는 선언 된 조인 순서에 따라 스트림을 정렬하는 것 같습니다. 즉 c, a, b, d, e, f, g, h
, 쿼리 계획에 차단 작업을 추가합니다.
내가 본 것들
- 열을
NOT NULL
동일한 결과 로 변경하려고했습니다 . - 원래 테이블은로 작성
ANSI_PADDING OFF
되었지만 이 테이블을 작성ANSI_PADDING ON
해도이 계획에는 영향을 미치지 않습니다. - 나는
INNER JOIN
대신에LEFT JOIN
변화를 시도했다 . - 2014 SP2 Enterprise에서 발견했으며 2017 개발자 (현재 CU)에서 재현을 만들었습니다.
- 선행 색인 열에서 WHERE 절을 제거하면 올바른 계획이 생성되지만 결과에 영향을 미칩니다 .. :)
마지막으로, 우리는 질문에 도달
- 이것은 의도적 인 것입니까?
- 쿼리를 변경하지 않고 정렬을 제거 할 수 있습니까 (공급 업체 코드이므로 실제로는 아닙니다 ...). 테이블과 인덱스를 변경할 수 있습니다.