PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

SQL:जब NOT IN और NOT EQUAL TO की बात आती है, तो कौन सा अधिक कुशल है और क्यों?

PostgreSQL में आमतौर पर उचित सूची लंबाई में काफी छोटा अंतर होता है, हालांकि IN अवधारणात्मक रूप से बहुत साफ है। बहुत लंबा AND ... <> ... सूचियाँ और बहुत लंबी NOT IN AND . के साथ दोनों सूचियां बहुत अच्छा प्रदर्शन करती हैं NOT IN . से भी बदतर ।

दोनों ही मामलों में, यदि वे इतने लंबे हैं कि आप प्रश्न पूछ सकते हैं, तो आपको इसके बजाय एक मूल्य सूची पर एक एंटी-जॉइन या सबक्वेरी बहिष्करण परीक्षण करना चाहिए।

WITH excluded(item) AS (
    VALUES('item1'), ('item2'), ('item3'), ('item4'),('item5')
)
SELECT * 
FROM thetable t
WHERE NOT EXISTS(SELECT 1 FROM excluded e WHERE t.item = e.item);

या:

WITH excluded(item) AS (
    VALUES('item1'), ('item2'), ('item3'), ('item4'),('item5')
)
SELECT * 
FROM thetable t
LEFT OUTER JOIN excluded e ON (t.item = e.item)
WHERE e.item IS NULL;

(आधुनिक पीजी संस्करणों पर दोनों वैसे भी एक ही क्वेरी प्लान तैयार करेंगे)।

यदि मूल्य सूची काफी लंबी है (कई दसियों हजारों आइटम) तो क्वेरी पार्सिंग की एक महत्वपूर्ण लागत शुरू हो सकती है। इस बिंदु पर आपको एक TEMPORARY बनाने पर विचार करना चाहिए टेबल, COPY डेटा को इसमें शामिल करना, संभवतः उस पर एक इंडेक्स बनाना, फिर सीटीई के बजाय अस्थायी तालिका पर उपरोक्त तरीकों में से एक का उपयोग करना।

डेमो:

CREATE UNLOGGED TABLE exclude_test(id integer primary key);
INSERT INTO exclude_test(id) SELECT generate_series(1,50000);
CREATE TABLE exclude AS SELECT x AS item FROM generate_series(1,40000,4) x;

जहां exclude छोड़े जाने वाले मानों की सूची है।

फिर मैं मिलीसेकंड में सभी परिणामों के साथ समान डेटा पर निम्नलिखित दृष्टिकोणों की तुलना करता हूं:

  • NOT IN सूची:3424.596
  • AND ... सूची:80173.823
  • VALUES आधारित JOIN बहिष्करण:20.727
  • VALUES आधारित सबक्वेरी बहिष्करण:20.495
  • तालिका-आधारित JOIN , पूर्व-सूची में कोई अनुक्रमणिका नहीं:25.183
  • उपश्रेणी आधारित तालिका, पूर्व-सूची पर कोई अनुक्रमणिका नहीं:23.985

... सीटीई-आधारित दृष्टिकोण को AND . की तुलना में तीन हजार गुना तेज बनाना सूची और NOT IN . से 130 गुना तेज सूची।

यहां कोड:https://gist.github.com/ringerc/5755247 (अपनी आंखों की रक्षा करें, जो इस लिंक का अनुसरण करते हैं)।

इस डेटा सेट आकार के लिए बहिष्करण सूची में एक इंडेक्स जोड़ने से कोई फर्क नहीं पड़ा।

नोट:

  • IN SELECT 'IN (' || string_agg(item::text, ',' ORDER BY item) || ')' from exclude;
  • AND SELECT string_agg(item::text, ' AND item <> ') from exclude; )
  • सबक्वायरी और जॉइन आधारित टेबल बहिष्करण दोहराए गए रनों में समान थे।
  • योजना की जांच से पता चलता है कि पीजी का अनुवाद NOT IN . होता है करने के लिए <> ALL

तो... आप देख सकते हैं कि वास्तव में एक विशाल है IN . दोनों के बीच गैप और AND सूचियाँ बनाम एक उचित जुड़ाव। मुझे आश्चर्य हुआ कि एक सीटीई के साथ VALUES . का उपयोग करके इसे कितनी तेजी से कर रहा था सूची थी ... VALUES को पार्स किया जा रहा है सूची में लगभग बिल्कुल भी समय नहीं लगा, वही प्रदर्शन कर रहा है या इससे थोड़ा तेज अधिकांश परीक्षणों में तालिका दृष्टिकोण।

यह अच्छा होगा यदि PostgreSQL स्वचालित रूप से एक लंबे समय तक IN recognize को पहचान सके समान AND . का खंड या शृंखला शर्तों और एक बेहतर दृष्टिकोण पर स्विच करें जैसे हैश जॉइन करना या इसे सीटीई नोड में बदलना। अभी यह नहीं जानता कि यह कैसे करना है।

यह भी देखें:

  • यह आसान ब्लॉग पोस्ट मैग्नस हैगेंडर ने इस विषय पर लिखा था


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL का उपयोग करके पिछले 24 घंटों के रिकॉर्ड का चयन कैसे करें

  2. PostgreSQL में टाइमस्टैम्प के आधार पर मूविंग एवरेज

  3. PostgreSQL के लिए एक इष्टतम वातावरण की स्थापना

  4. पोस्टग्रेज टिप्स एंड ट्रिक्स

  5. कैसे पता करें कि पोस्टग्रेएसक्यूएल 9.5+ यूपीएसईआरटी के साथ एक अप्सर्ट अपडेट था या नहीं?