नमूना डेटा दिया गया:
create table results ( commandid integer primary key);
insert into results (commandid) select * from generate_series(1,1000);
delete from results where random() < 0.20;
यह काम करता है:
SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
WHERE NOT EXISTS (SELECT 1 FROM results WHERE commandid = s.i);
जैसा कि यह वैकल्पिक सूत्रीकरण करता है:
SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
LEFT OUTER JOIN results ON (results.commandid = s.i)
WHERE results.commandid IS NULL;
उपरोक्त दोनों मेरे परीक्षणों में समान क्वेरी योजनाओं के परिणाम के रूप में दिखाई देते हैं, लेकिन आपको EXPLAIN ANALYZE
का उपयोग करके अपने डेटाबेस पर अपने डेटा के साथ तुलना करनी चाहिए। यह देखने के लिए कि कौन सा सबसे अच्छा है।
स्पष्टीकरण
ध्यान दें कि NOT IN
. के बजाय मैंने NOT EXISTS
. का उपयोग किया है एक फॉर्मूलेशन में एक सबक्वायरी के साथ, और एक सामान्य OUTER JOIN
अन्य में। डीबी सर्वर के लिए इन्हें अनुकूलित करना बहुत आसान है और यह भ्रमित करने वाले मुद्दों से बचा जाता है जो NULL
के साथ उत्पन्न हो सकते हैं। में NOT IN
।
मैंने शुरू में OUTER JOIN
का समर्थन किया था फॉर्मूलेशन, लेकिन कम से कम 9.1 में मेरे टेस्ट डेटा के साथ NOT EXISTS
फ़ॉर्म उसी योजना के लिए अनुकूलित होता है।
दोनों NOT IN
. से बेहतर प्रदर्शन करेंगे जब श्रृंखला बड़ी हो, जैसा कि आपके मामले में है। NOT IN
IN
. की रैखिक खोज करने के लिए Pg की आवश्यकता होती है प्रत्येक टपल का परीक्षण किया जा रहा है, लेकिन क्वेरी योजना की जांच से पता चलता है कि पीजी अब इसे हैश करने के लिए पर्याप्त स्मार्ट हो सकता है। NOT EXISTS
(JOIN
. में रूपांतरित क्वेरी प्लानर द्वारा) और JOIN
बेहतर काम करें।
NOT IN
NULL commandid
. की उपस्थिति में फॉर्मूलेशन दोनों भ्रमित करने वाला है s और अक्षम हो सकते हैं:
SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
WHERE s.i NOT IN (SELECT commandid FROM results);
तो मैं इससे बचूंगा। 1,000,000 पंक्तियों के साथ अन्य दो 1.2 सेकंड में पूर्ण हुए और NOT IN
जब तक मैं ऊब नहीं गया और इसे रद्द नहीं कर दिया, तब तक फॉर्मूलेशन सीपीयू-बाध्य था।