Sql-Server
當我在兩個索引視圖上通過聚集索引進行內部聯接時,為什麼查詢處理器不能生成帶有 FORCESEEK 提示的查詢計劃?
當我嘗試將 FORCESEEK 提示與以下查詢一起使用時,出現以下錯誤:
消息 8622,級別 16,狀態 1,第 96 行 由於此查詢中定義的提示,查詢處理器無法生成查詢計劃。在不指定任何提示且不使用 SET FORCEPLAN 的情況下重新送出查詢。
SELECT A.IndexedField1 INTO #TEMP FROM dbo.IndexedView1 AS A WITH (FORCESEEK) INNER JOIN dbo.IndexedView2 AS B ON A.IndexedField1 = B.IndexedField1 AND A.IndexedField2 = B.IndexedField2
IndexedView1 和IndexedView2 都是模式綁定的索引視圖,並且在兩個視圖的IndexedField1、IndexedField2 欄位上都有一個唯一的聚集索引。不確定是否相關,但聚集索引有 40 字節大(每行)。
下面是兩個視圖在引擎蓋下的樣子的範例:
SELECT IndexedField1, RIGHT(CONVERT(VARCHAR(34), HASHBYTES('MD5', OtherField1 + '||' OtherField2)), 32) AS IndexedField2 FROM dbo.Table1
沒什麼太花哨的,視圖查詢中也沒有提示。
這是一個複製品。據記錄,您不能在沒有NOEXPAND的索引視圖上使用 FORCESEEK 。
例如
drop table if exists table1 drop table if exists table2 go create table Table1(IndexedField1 int, OtherField1 nvarchar(200), OtherField2 nvarchar(200)) create table Table2(IndexedField1 int, OtherField1 nvarchar(200), OtherField2 nvarchar(200)) go create view IndexedView1 with schemabinding as SELECT IndexedField1, RIGHT(CONVERT(VARCHAR(34), HASHBYTES('MD5', OtherField1 + '||' + OtherField2)), 32) AS IndexedField2 FROM dbo.Table1 go create view IndexedView2 with schemabinding as SELECT IndexedField1, RIGHT(CONVERT(VARCHAR(34), HASHBYTES('MD5', OtherField1 + '||' + OtherField2)), 32) AS IndexedField2 FROM dbo.Table2 go create unique clustered index pk_IndexedView1 on IndexedView1(IndexedField1,IndexedField2) create unique clustered index pk_IndexedView2 on IndexedView2(IndexedField1,IndexedField2) go SELECT A.IndexedField1 INTO #TEMP FROM dbo.IndexedView1 AS A WITH (FORCESEEK) INNER JOIN dbo.IndexedView2 AS B ON A.IndexedField1 = B.IndexedField1 AND A.IndexedField2 = B.IndexedField2 /* Msg 8622, Level 16, State 1, Line 34 Query processor could not produce a query plan because of the hints defined in this query. Resubmit the query without specifying any hints and without using SET FORCEPLAN. */ go drop table if exists #TEMP SELECT A.IndexedField1 INTO #TEMP FROM dbo.IndexedView1 AS A with (noexpand) INNER JOIN dbo.IndexedView2 AS B with (noexpand) ON A.IndexedField1 = B.IndexedField1 AND A.IndexedField2 = B.IndexedField2
執行計劃:
在應用 NOEXPAND 並指定計劃應該只涉及視圖索引之後,您可以使用 FORCESEEK 提示,或者根據需要指定連接樣式(MERGE、LOOP 或 HASH)。
例如
SELECT A.IndexedField1 INTO #TEMP FROM dbo.IndexedView1 AS A WITH (NOEXPAND) INNER MERGE JOIN dbo.IndexedView2 AS B ON A.IndexedField1 = B.IndexedField1 AND A.IndexedField2 = B.IndexedField2