설명서가 약간 잘못되었습니다. DMV는 구체화되지 않은 뷰이므로 기본 키는 없습니다. 기본 정의는 약간 복잡하지만 다음과 같이 단순화 된 정의 sys.query_store_plan
는 다음과 같습니다.
CREATE VIEW sys.query_store_plan AS
SELECT
PPM.plan_id
-- various other attributes
FROM sys.plan_persist_plan_merged AS PPM
LEFT JOIN sys.syspalvalues AS P
ON P.class = 'PFT'
AND P.[value] = plan_forcing_type;
또한 sys.plan_persist_plan_merged
정의를 보려면 전용 관리자 연결을 통해 연결해야하지만보기입니다. 다시 한 번 단순화합니다.
CREATE VIEW sys.plan_persist_plan_merged AS
SELECT
P.plan_id as plan_id,
-- various other attributes
FROM sys.plan_persist_plan P
-- NOTE - in order to prevent potential deadlock
-- between QDS_STATEMENT_STABILITY LOCK and index locks
WITH (NOLOCK)
LEFT JOIN sys.plan_persist_plan_in_memory PM
ON P.plan_id = PM.plan_id;
인덱스 sys.plan_persist_plan
는 다음과 같습니다.
╔ ==================================================== ================ ╦ =============== ╗
_ index_name ║ index_description ║ index_keys ║
╠ ==================================================== ================ ╬ =============== ╣
IM plan_persist_plan_cidx ║ 클러스터에 있으며 고유 한 위치는 PRIMARY ║ plan_id ║
IM plan_persist_plan_idx1 PR PRIMARY에있는 비 클러스터 ║ query_id (-) ║
╚ ==================================================== ================ ╩ =============== ╝
따라서 plan_id
에 고유 한 것으로 제한됩니다 sys.plan_persist_plan
.
이제는 sys.plan_persist_plan_in_memory
스트리밍 테이블 값 함수로 내부 메모리 구조에만있는 데이터의 테이블 형식보기를 제공합니다. 따라서 고유 한 제한 조건이 없습니다.
따라서 실행중인 쿼리는 다음과 같습니다.
DECLARE @t1 table (plan_id integer NOT NULL);
DECLARE @t2 table (plan_id integer NOT NULL UNIQUE CLUSTERED);
DECLARE @t3 table (plan_id integer NULL);
SELECT
T1.plan_id
FROM @t1 AS T1
LEFT JOIN
(
SELECT
T2.plan_id
FROM @t2 AS T2
LEFT JOIN @t3 AS T3
ON T3.plan_id = T2.plan_id
) AS Q1
ON Q1.plan_id = T1.plan_id;
... 결합 제거를 생성하지 않습니다.
문제의 핵심에 바로 도달하면 문제는 내부 쿼리입니다.
DECLARE @t2 table (plan_id integer NOT NULL UNIQUE CLUSTERED);
DECLARE @t3 table (plan_id integer NULL);
SELECT
T2.plan_id
FROM @t2 AS T2
LEFT JOIN @t3 AS T3
ON T3.plan_id = T2.plan_id;
...에 대한 고유 제약 조건이 없으므로 왼쪽 조인으로 인해 행 @t2
이 복제 @t3
되지 않을 수 있습니다 plan_id
. 따라서 조인을 제거 할 수 없습니다.
이 문제를 해결하기 위해 중복 plan_id
값이 필요하지 않다고 명시 적으로 최적화 프로그램에 알릴 수 있습니다 .
DECLARE @t2 table (plan_id integer NOT NULL UNIQUE CLUSTERED);
DECLARE @t3 table (plan_id integer NULL);
SELECT DISTINCT
T2.plan_id
FROM @t2 AS T2
LEFT JOIN @t3 AS T3
ON T3.plan_id = T2.plan_id;
외부 조인을 @t3
이제 제거 할 수 있습니다.
실제 쿼리에 적용 :
SELECT DISTINCT
T.plan_id
FROM #tears AS T
LEFT JOIN sys.query_store_plan AS QSP
ON QSP.plan_id = T.plan_id;
마찬가지로 . GROUP BY T.plan_id
대신 추가 할 수 있습니다 DISTINCT
. 어쨌든, 옵티마이 저는 이제 plan_id
중첩 뷰를 통해 속성 에 대해 올바르게 추론 하고 원하는대로 두 개의 외부 조인을 제거 할 수 있습니다.
plan_id
임시 테이블에서 고유 하게 만드는 것은 잘못된 결과를 배제하지 않기 때문에 조인 제거를 얻기에 충분하지 않습니다. plan_id
옵티마이 저가 여기서 마법을 사용할 수 있도록 최종 결과에서 중복 값을 명시 적으로 거부해야합니다 .