यह पूरी तरह से एक विहित जवाब नहीं है, लेकिन मैंने देखा है कि SQL फिडेल में दिखाए गए नेस्टेड लूप्स क्वेरी प्लान के लिए क्विंट 2 से क्वैरी 1 तक की योजना को USE PLAN
संकेत के उपयोग के साथ लागू करना संभव था, लेकिन रिवर्स ऑपरेशन का प्रयास विफल रहा
क्वेरी प्रोसेसर क्वेरी योजना का उत्पादन नहीं कर सका क्योंकि USE PLAN संकेत में वह योजना होती है जिसे क्वेरी के लिए वैध होने के लिए सत्यापित नहीं किया जा सकता है। USE PLAN संकेत निकालें या प्रतिस्थापित करें। सफल योजना के सर्वोत्तम संभावना के लिए, सत्यापित करें कि USE PLAN संकेत में प्रदान की गई योजना एक ही क्वेरी के लिए SQL सर्वर द्वारा स्वचालित रूप से बनाई गई है।
ऑप्टिमाइज़र परिवर्तन नियम ReorderLOJN
को अक्षम करने से पहले की सफल योजना संकेत को भी सफल होने से रोकता है।
अधिक मात्रा में डेटा के साथ प्रयोग करने से पता चलता है कि एसक्यूएल सर्वर निश्चित रूप (A LOJ B) LOJ C
से A LOJ (B LOJ C)
स्वाभाविक रूप से रूपांतरित करने में सक्षम है, लेकिन मुझे ऐसा कोई प्रमाण नहीं मिला कि रिवर्स सच है।
एक बहुत ही विवादित मामला जहां पहली क्वेरी दूसरी से बेहतर प्रदर्शन करती है
DROP TABLE MyGrandChild , MyChild, MyParent
CREATE TABLE MyParent
(Id int)
CREATE TABLE MyChild
(Id int PRIMARY KEY
,ParentId int,
Filler char(8000) NULL)
CREATE TABLE MyGrandChild
(Id int
,ParentId int)
INSERT INTO MyChild
(Id, ParentId)
SELECT TOP (100000) ROW_NUMBER() OVER (ORDER BY @@SPID),
ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values v1, master..spt_values
INSERT INTO MyGrandChild
(Id, ParentId)
OUTPUT INSERTED.Id INTO MyParent
SELECT TOP (3000) Id, Id AS ParentId
FROM MyChild
ORDER BY Id
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
SELECT gc.Id AS gcId,
gc.ParentId AS gcpId,
c.Id AS cId,
c.ParentId AS cpId,
p.Id AS pId
FROM MyGrandChild AS gc
LEFT OUTER JOIN MyChild AS c
ON c.[Id] = gc.[ParentId]
LEFT OUTER JOIN MyParent AS p
ON p.[Id] = c.[ParentId]
SELECT gc.Id AS gcId,
gc.ParentId AS gcpId,
c.Id AS cId,
c.ParentId AS cpId,
p.Id AS pId
FROM MyGrandChild AS gc
LEFT OUTER JOIN( MyChild AS c
LEFT OUTER JOIN MyParent AS p
ON p.[Id] = c.[ParentId])
ON c.[Id] = gc.[ParentId]
जो योजना देता है
मेरे लिए क्वेरी 1 में क्वेरी 2 के लिए 108 एमएस बनाम 1,163 एमएस का एक विस्तृत समय था।
प्रश्न 1
Table 'Worktable'. Scan count 0, logical reads 0
Table 'MyChild'. Scan count 0, logical reads 9196
Table 'MyGrandChild'. Scan count 1, logical reads 7
Table 'MyParent'. Scan count 1, logical reads 5
प्रश्न २
Table 'MyParent'. Scan count 1, logical reads 15000
Table 'MyChild'. Scan count 0, logical reads 9000
Table 'MyGrandChild'. Scan count 1, logical reads 7
तो यह अनंतिम रूप से माना जा सकता है कि पहला ("अनावश्यक") सिंटैक्स संभावित रूप से फायदेमंद है क्योंकि यह अधिक संभावित शामिल होने के आदेशों पर विचार करने की अनुमति देता है, लेकिन मैंने एक सामान्य नियम के रूप में इस पर बहुत विश्वास करने के लिए पर्याप्त परीक्षण नहीं किया है।
यह अच्छी तरह से काउंटर उदाहरणों के साथ आने के लिए पूरी तरह से संभव हो सकता है जहां क्वेरी 2 बेहतर प्रदर्शन करती है। दोनों का प्रयास करें और निष्पादन योजनाओं को देखें।