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

WHERE क्लॉज में एक ही कॉलम को कई बार इस्तेमाल करना

यह संबंधपरक-विभाजन का मामला है। मैंने टैग जोड़ा।

सूचकांक

USER_PROPERTY_MAP(property_value_id, user_id) पर PK या UNIQUE बाधा मानकर - इस क्रम में कॉलम मेरे प्रश्नों को तेज करने के लिए। संबंधित:

  • क्या पहले फ़ील्ड पर प्रश्नों के लिए एक समग्र अनुक्रमणिका भी अच्छी है?

आपके पास PROPERTY_VALUE(value, property_name_id, id) पर एक अनुक्रमणिका भी होनी चाहिए . फिर से, इस क्रम में कॉलम। अंतिम कॉलम जोड़ें id केवल तभी जब आपको इसका केवल-अनुक्रमणीय स्कैन प्राप्त हो।

दी गई संपत्तियों की संख्या के लिए

इसे हल करने के कई तरीके हैं। यह बिल्कुल दो . के लिए सबसे सरल और तेज़ में से एक होना चाहिए गुण:

SELECT u.*
FROM   users             u
JOIN   user_property_map up1 ON up1.user_id = u.id
JOIN   user_property_map up2 USING (user_id)
WHERE  up1.property_value_id =
      (SELECT id FROM property_value WHERE property_name_id = 1 AND value = '101')
AND    up2.property_value_id =
      (SELECT id FROM property_value WHERE property_name_id = 2 AND value = '102')
-- AND    u.user_name = 'user1'  -- more filters?
-- AND    u.city = 'city1'

टेबल पर नहीं जा रहे PROPERTY_NAME , क्योंकि ऐसा लगता है कि आपने अपनी उदाहरण क्वेरी के अनुसार पहले से ही आईडी के लिए संपत्ति के नाम हल कर लिए हैं। नहीं तो आप PROPERTY_NAME में एक जॉइन जोड़ सकते हैं प्रत्येक सबक्वेरी में।

हमने इस संबंधित प्रश्न के तहत तकनीकों का एक शस्त्रागार इकट्ठा किया है:

  • एक हैस-मैनी-थ्रू संबंध में SQL परिणामों को कैसे फ़िल्टर करें

अज्ञात संख्या में प्रॉपर्टी के लिए

@Mike और @Valera के अपने-अपने उत्तरों में बहुत उपयोगी प्रश्न हैं। इसे और भी अधिक गतिशील बनाने के लिए :

WITH input(property_name_id, value) AS (
      VALUES  -- provide n rows with input parameters here
        (1, '101')
      , (2, '102')
      -- more?
      ) 
SELECT *
FROM   users u
JOIN  (
   SELECT up.user_id AS id
   FROM   input
   JOIN   property_value    pv USING (property_name_id, value)
   JOIN   user_property_map up ON up.property_value_id = pv.id
   GROUP  BY 1
   HAVING count(*) = (SELECT count(*) FROM input)
   ) sub USING (id);

केवल VALUES . से पंक्तियां जोड़ें/हटाएं अभिव्यक्ति। या WITH हटा दें खंड और JOIN कोई संपत्ति फ़िल्टर नहीं . के लिए बिल्कुल।

समस्या प्रश्नों के इस वर्ग के साथ (सभी आंशिक मिलानों की गणना करना) प्रदर्शन . है . मेरी पहली क्वेरी कम गतिशील है, लेकिन आम तौर पर काफी तेज है। (बस EXPLAIN ANALYZE के साथ परीक्षण करें ।) विशेष रूप से बड़ी तालिकाओं और संपत्तियों की बढ़ती संख्या के लिए।

दोनों दुनिया के सर्वश्रेष्ठ?

पुनरावर्ती CTE वाला यह समाधान एक अच्छा समझौता होना चाहिए:तेज़ और गतिशील:

WITH RECURSIVE input AS (
   SELECT count(*)     OVER () AS ct
        , row_number() OVER () AS rn
        , *
   FROM  (
      VALUES  -- provide n rows with input parameters here
        (1, '101')
      , (2, '102')
      -- more?
      ) i (property_name_id, value)
   )
 , rcte AS (
   SELECT i.ct, i.rn, up.user_id AS id
   FROM   input             i
   JOIN   property_value    pv USING (property_name_id, value)
   JOIN   user_property_map up ON up.property_value_id = pv.id
   WHERE  i.rn = 1

   UNION ALL
   SELECT i.ct, i.rn, up.user_id
   FROM   rcte              r
   JOIN   input             i ON i.rn = r.rn + 1
   JOIN   property_value    pv USING (property_name_id, value)
   JOIN   user_property_map up ON up.property_value_id = pv.id
                              AND up.user_id = r.id
   )
SELECT u.*
FROM   rcte  r
JOIN   users u USING (id)
WHERE  r.ct = r.rn;          -- has all matches

यहां dbfiddle

पुनरावर्ती सीटीई के बारे में मैनुअल।

अतिरिक्त जटिलता छोटी तालिकाओं के लिए भुगतान नहीं करती है जहां अतिरिक्त ओवरहेड किसी भी लाभ से अधिक है या अंतर शुरू करने के लिए नगण्य है। लेकिन यह बहुत बेहतर पैमाने पर है और बढ़ती तालिकाओं और संपत्ति फिल्टर की बढ़ती संख्या के साथ "गिनती" तकनीकों से बेहतर होता जा रहा है।

गिनती तकनीकों को सभी पर जाना होगा user_property_map में पंक्तियां सभी दिए गए प्रॉपर्टी फ़िल्टर के लिए, जबकि यह क्वेरी (साथ ही पहली क्वेरी) अप्रासंगिक उपयोगकर्ताओं को जल्दी खत्म कर सकती है।

प्रदर्शन अनुकूलित करना

वर्तमान तालिका आँकड़ों के साथ (उचित सेटिंग्स, autovacuum चल रहा है), पोस्टग्रेज़ को "सबसे सामान्य मूल्यों" . के बारे में जानकारी है प्रत्येक कॉलम में और पहली क्वेरी . में शामिल होने का क्रम बदलेगा पहले सबसे चुनिंदा प्रॉपर्टी फ़िल्टर का मूल्यांकन करने के लिए (या कम से कम चुनिंदा वाले नहीं)। एक निश्चित सीमा तक:join_collapse_limit . संबंधित:

  • Postgresql join_collapse_limit और क्वेरी प्लानिंग के लिए समय
  • खोज शब्द में थोड़ा सा बदलाव क्वेरी को इतना धीमा क्यों कर देता है?

तीसरी क्वेरी के साथ यह "deus-ex-machina" हस्तक्षेप संभव नहीं है (पुनरावर्ती सीटीई)। प्रदर्शन में मदद करने के लिए (संभवतः बहुत अधिक) आपको पहले स्वयं अधिक चयनात्मक फ़िल्टर लगाने होंगे। लेकिन सबसे खराब स्थिति में भी यह गिनती के प्रश्नों से बेहतर प्रदर्शन करेगा।

संबंधित:

  • पोस्टग्रेएसक्यूएल में आंकड़े लक्ष्य जांचें

बहुत अधिक रक्तरंजित विवरण:

  • मौजूदा डेटा वाली तालिका में बनाए जाने पर PostgreSQL आंशिक अनुक्रमणिका अप्रयुक्त होती है

मैनुअल में अधिक स्पष्टीकरण:

  • नियोजक द्वारा उपयोग किए गए आंकड़े


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. पोस्टग्रेज में डेटाबेस कैसे स्विच करें?

  2. PostgreSql का उपयोग करके Ireports में छवि प्रदर्शित करना

  3. PostgreSQL अनुक्रमों का अगला मान?

  4. PostgreSQL में महीने दर महीने वृद्धि की गणना कैसे करें

  5. अनुरोधित सेवा बनाने में असमर्थ [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]