मैं हमेशा NOT EXISTS
पर डिफ़ॉल्ट हूं।
निष्पादन की योजना इस समय एक ही हो सकता है, लेकिन यदि या तो स्तंभ भविष्य में बदल दिया जाता है NULL
अनुमति देने के लिए है NOT IN
संस्करण अधिक काम करने के (भले ही कोई NULL
रों वास्तव में डेटा में मौजूद हैं) की आवश्यकता होगी और NOT IN
के अर्थशास्त्र यदि NULL
s वर्तमान में वैसे भी होने की संभावना नहीं है।
जब न Products.ProductID
या [Order Details].ProductID
अनुमति देते हैं NULL
रों NOT IN
निम्न क्वेरी के समान माना जाएगा।
SELECT ProductID,
ProductName
FROM Products p
WHERE NOT EXISTS (SELECT *
FROM [Order Details] od
WHERE p.ProductId = od.ProductId)
सटीक योजना भिन्न हो सकती है लेकिन मेरे उदाहरण डेटा के लिए मुझे निम्न मिलता है।
एक यथोचित आम धारणा है कि सहसंबद्ध उप प्रश्नों हमेशा मिलती है की तुलना में "बुरा" हैं लगता है। वे निश्चित रूप से तब हो सकते हैं जब वे एक नेस्टेड लूप योजना (पंक्ति द्वारा उप क्वेरी मूल्यांकन पंक्ति) को मजबूर करते हैं लेकिन इस योजना में एक विरोधी सेमीफाइनल लॉजिकल ऑपरेटर शामिल है। एंटी अर्द्ध जॉइन नेस्टेड लूप तक ही सीमित नहीं हैं लेकिन हैश या मर्ज का उपयोग कर सकते हैं (जैसा कि इस उदाहरण में) भी शामिल हो जाता है।
/*Not valid syntax but better reflects the plan*/
SELECT p.ProductID,
p.ProductName
FROM Products p
LEFT ANTI SEMI JOIN [Order Details] od
ON p.ProductId = od.ProductId
तो [Order Details].ProductID
NULL
है सुलभ क्वेरी तो हो जाता है
SELECT ProductID,
ProductName
FROM Products p
WHERE NOT EXISTS (SELECT *
FROM [Order Details] od
WHERE p.ProductId = od.ProductId)
AND NOT EXISTS (SELECT *
FROM [Order Details]
WHERE ProductId IS NULL)
इस का कारण यह सही अर्थ विज्ञान अगर [Order Details]
शामिल है कि किसी भी NULL
ProductId
कोई परिणाम देने के है। योजना में जोड़े गए यह सत्यापित करने के लिए अतिरिक्त एंटी सेमी सेमी और पंक्ति गणना स्पूल देखें।
तो Products.ProductID
भी NULL
बनने के लिए सुलभ क्वेरी तो हो जाता है
SELECT ProductID,
ProductName
FROM Products p
WHERE NOT EXISTS (SELECT *
FROM [Order Details] od
WHERE p.ProductId = od.ProductId)
AND NOT EXISTS (SELECT *
FROM [Order Details]
WHERE ProductId IS NULL)
AND NOT EXISTS (SELECT *
FROM (SELECT TOP 1 *
FROM [Order Details]) S
WHERE p.ProductID IS NULL)
बदल गया है कि एक के लिए कारण यह है कि एक NULL
Products.ProductId
छोड़कर परिणामों में नहीं किया जाना चाहिए यदि NOT IN
उप क्वेरी को कोई परिणाम नहीं लौटा रहा था (यानी [Order Details]
तालिका खाली है)। इस मामले में यह होना चाहिए। मेरे नमूना डेटा के लिए योजना में यह नीचे एक और विरोधी अर्द्ध शामिल जोड़कर लागू किया गया है।
इस के प्रभाव the blog post already linked by Buckley में दिखाया गया है। उदाहरण में वहां लॉजिकल रीड की संख्या लगभग 400 से 500,000 तक बढ़ जाती है।
इसके अतिरिक्त यह तथ्य कि एक NULL
पंक्ति गणना को शून्य तक कम कर सकता है कार्डिनिटी अनुमान बहुत मुश्किल बनाता है। यदि SQL सर्वर मानता है कि ऐसा होगा लेकिन वास्तव में डेटा में NULL
पंक्तियां नहीं थीं, शेष निष्पादन योजना विनाशकारी रूप से खराब हो सकती है, अगर यह केवल एक बड़ी क्वेरी का हिस्सा है, with inappropriate nested loops causing repeated execution of an expensive sub tree for example।
यह एक NULL
सुलभ स्तंभ पर एक NOT IN
तथापि के लिए ही संभव कार्य योजना लागू नहीं है। AdventureWorks2008
डेटाबेस के विरुद्ध एक प्रश्न के लिए This article shows another one।
एक NOT NULL
स्तंभ पर NOT IN
या या तो एक नल या गैर व्यर्थ स्तम्भ के खिलाफ NOT EXISTS
यह निम्न योजना देता है के लिए ।
NULL
करने के लिए स्तंभ परिवर्तन सुलभ NOT IN
योजना अब लग रहा है जब
तरह यह एक अतिरिक्त भीतरी कहते योजना के लिए ऑपरेटर में शामिल हो। यह उपकरण explained here है। पिछले एकल सहसंबंधित इंडेक्स को Sales.SalesOrderDetail.ProductID = <correlated_product_id>
पर दो बाहरी पंक्तियों की तलाश में बदलने के लिए यह सब कुछ है। अतिरिक्त एक WHERE Sales.SalesOrderDetail.ProductID IS NULL
पर है।
चूंकि यह एक अर्द्ध अर्द्ध शामिल है, यदि कोई भी पंक्तियों को वापस करता है तो दूसरा प्रयास नहीं होगा। हालांकि अगर Sales.SalesOrderDetail
में कोई NULL
ProductID
नहीं है तो यह आवश्यक संचालन संचालन की संख्या को दोगुना कर देगा।
क्या आपने एक बाएं शामिल होने के साथ योजना का प्रयास किया है जहां शून्य है? – Sebas
मुझे आश्चर्य है कि डेटाबेस अलग हैं, लेकिन PostgreSQL के खिलाफ मेरे नवीनतम बेंचमार्क में, यह 'इन नहीं' क्वेरी है: 'चुनें "ए"। * "ए" से "ए"। "आईडी" नहीं (चयन करें "बी"। " सहायता "बी" कहां "बी"। "यूआईडी" = 2) 'लगभग 15 गुना तेज है क्योंकि यह 'पूर्व नहीं है': 'चुनें" ए "। *" ए "से (नहीं (EXISTS (चयन 1) "बी" से "बी"। "User_id" = 2 और "बी"। "सहायता" = "ए"। "आईडी"))) –
संभावित डुप्लिकेट [EXISTS बनाम नहीं बनाम बनाम अंतर के बीच क्या अंतर है बाएं जॉइन कहां है?] (Http://stackoverflow.com/questions/2246772/whats-the-difference-between-not-exists-vs-not-in-vs-left- join-where-is-null) – rcdmk