Dokumentasinya sedikit menyesatkan. DMV adalah pandangan yang tidak terwujud, dan tidak memiliki kunci primer seperti itu. Definisi yang mendasarinya sedikit rumit tetapi definisi yang disederhanakan sys.query_store_plan
adalah:
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;
Lebih lanjut, sys.plan_persist_plan_merged
ini juga merupakan pandangan, meskipun seseorang harus terhubung melalui Koneksi Administrator Khusus untuk melihat definisinya. Sekali lagi, disederhanakan:
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;
Indeks yang aktif sys.plan_persist_plan
adalah:
╔════════════════════════╦════════════════════════ ══════════════╦═════════════╗
║ index_name ║ index_description ║ index_keys ║
╠════════════════════════╬════════════════════════ ══════════════╬═════════════╣
║ plan_persist_plan_cidx ║ berkerumun, unik terletak di PRIMARY ║ plan_id ║
║ plan_persist_plan_idx1 ║ nonclustered terletak di PRIMARY ║ query_id (-) ║
╚════════════════════════╩════════════════════════ ══════════════╩═════════════╝
Jadi plan_id
dibatasi untuk menjadi unik sys.plan_persist_plan
.
Sekarang, sys.plan_persist_plan_in_memory
adalah fungsi streaming yang dihargai tabel, menyajikan tampilan tabular data yang hanya disimpan dalam struktur memori internal. Karena itu, tidak memiliki kendala unik.
Karena itu, kueri yang dijalankan setara dengan:
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;
... yang tidak menghasilkan eliminasi gabungan:
Langsung ke inti masalah, masalahnya adalah kueri batin:
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;
... jelas gabung kiri mungkin menghasilkan baris dari @t2
duplikasi karena @t3
tidak memiliki kendala keunikan plan_id
. Karenanya, join tidak dapat dihilangkan:
Untuk mengatasinya, kami dapat secara eksplisit memberi tahu pengoptimal bahwa kami tidak memerlukan plan_id
nilai duplikat :
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;
Gabung luar ke @t3
sekarang dapat dihilangkan:
Menerapkannya ke permintaan sebenarnya:
SELECT DISTINCT
T.plan_id
FROM #tears AS T
LEFT JOIN sys.query_store_plan AS QSP
ON QSP.plan_id = T.plan_id;
Sama, kita bisa menambahkan GROUP BY T.plan_id
bukan DISTINCT
. Pokoknya, pengoptimal sekarang dapat dengan benar alasan tentang plan_id
atribut sepanjang jalan melalui tampilan bersarang, dan menghilangkan kedua gabungan luar yang diinginkan:
Perhatikan bahwa membuat plan_id
unik di tabel sementara tidak akan cukup untuk mendapatkan eliminasi gabungan, karena itu tidak akan menghalangi hasil yang salah. Kami harus secara eksplisit menolak plan_id
nilai duplikat dari hasil akhir untuk memungkinkan pengoptimal bekerja dengan baik di sini.