我有一個表項目值全中,看起來像2000兼容模式下運行的SQL 2005服務器上的數據(這是一個用戶定義的值表):SQL優化 - 執行計劃基於約束值更改 - 爲什麼?
ID ItemCode FieldID Value
-- ---------- ------- ------
1 abc123 1 D
2 abc123 2 287.23
4 xyz789 1 A
5 xyz789 2 3782.23
6 xyz789 3 23
7 mno456 1 W
9 mno456 3 45
... and so on.
FieldID來自在ItemField表:
ID FieldNumber DataFormatID Description ...
-- ----------- ------------ -----------
1 1 1 Weight class
2 2 4 Cost
3 3 3 Another made up description
. . x xxx
. . x xxx
. . x xxx
x 91 (we have 91 user-defined fields)
因爲我不能PIVOT在2000模式下,我們堅持用建設情況和GROUP BY來獲取數據的醜陋查詢一下應該如何對於s青梅遺留應用程序,這就是:
ItemNumber Field1 Field2 Field3 .... Field51
---------- ------ ------- ------
abc123 D 287.23 NULL
xyz789 A 3782.23 23
mno456 W NULL 45
你可以看到,我們只需要該表顯示值高達第51 UDF。這裏的查詢:
SELECT
iv.ItemNumber,
,MAX(CASE WHEN f.FieldNumber = 1 THEN iv.[Value] ELSE NULL END) [Field1]
,MAX(CASE WHEN f.FieldNumber = 2 THEN iv.[Value] ELSE NULL END) [Field2]
,MAX(CASE WHEN f.FieldNumber = 3 THEN iv.[Value] ELSE NULL END) [Field3]
...
,MAX(CASE WHEN f.FieldNumber = 51 THEN iv.[Value] ELSE NULL END) [Field51]
FROM ItemField f
LEFT JOIN ItemValue iv ON f.ID = iv.FieldID
WHERE f.FieldNumber <= 51
GROUP BY iv.ItemNumber
當FieldNumber約束是< = 51,執行計劃進行類似:
SELECT <== Computer Scalar <== Stream Aggregate <== Sort (Cost: 70%) <== Hash Match <== (Clustered Index Seek && Table Scan)
而且速度快!我可以在大約一秒鐘內恢復100,000多條記錄,這符合我們的需求。
然而,如果我們有更多的UDF和我改變約束到任何上述(是的,我測試了他們一個接一個),或者如果我完全刪除了,我失去了排序的執行計劃,並被一大堆並行性塊取代,這些塊收集,重新分配和分配流,整個事情很慢(即使只有一條記錄,也只需30秒)。
FieldNumber具有羣集的,唯一的索引,並且是在ItemField表與ID柱(非聚集索引)複合主鍵的一部分。該項目值表的ID和ItemNumber列進行PK,並沒有對ItemNumber列額外的非聚集索引。
這是什麼原因?爲什麼更改我的簡單整數約束會改變整個執行計劃?
如果你決定了...... 你會做什麼不同?從現在開始計劃幾個月的SQL升級,但在此之前我需要解決此問題。
我會做不同的是不使用表結構。使用具有定義字段的結構可以提前計算99%的數據需求,而不是使用EAV表。順便提一下,兼容模式並不妨礙您使用新功能,而是允許使用不再允許的功能。但是,如果您正在使用2000生產數據庫的2005數據庫進行開發,則最好避免使用新功能。 – HLGEM 2011-06-08 17:51:29