एक बड़ा OFFSET
हमेशा धीमा रहेगा। पोस्टग्रेज़ को सभी पंक्तियों को क्रमित करना होता है और दृश्यमान . की गणना करनी होती है आपके ऑफसेट तक वाले। पिछली सभी पंक्तियों को छोड़ने के लिए सीधे आप एक अनुक्रमित row_number
जोड़ सकते हैं तालिका में (या एक MATERIALIZED VIEW
बनाएं) उक्त row_number
. सहित ) और WHERE row_number > x
. के साथ काम करें OFFSET x
. के बजाय ।
हालाँकि, यह दृष्टिकोण केवल-पढ़ने के लिए (या अधिकतर) डेटा के लिए ही समझदार है। तालिका डेटा के लिए इसे लागू करना जो समवर्ती रूप से बदल सकता है अधिक चुनौतीपूर्ण है। आपको वांछित व्यवहार को परिभाषित करके प्रारंभ करना होगा बिल्कुल ।
मैं पेजिनेशन . के लिए एक अलग दृष्टिकोण सुझाता हूं :
SELECT *
FROM big_table
WHERE (vote, id) > (vote_x, id_x) -- ROW values
ORDER BY vote, id -- needs to be deterministic
LIMIT n;
जहां vote_x
और id_x
अंतिम . से हैं पिछला पृष्ठ . की पंक्ति (दोनों के लिए DESC
और ASC
) या पहले . से अगर नेविगेट कर रहे हैं पीछे की ओर ।
पंक्ति मानों की तुलना आपके पास पहले से मौजूद इंडेक्स द्वारा समर्थित है - एक ऐसी सुविधा जो आईएसओ एसक्यूएल मानक का अनुपालन करती है, लेकिन प्रत्येक आरडीबीएमएस इसका समर्थन नहीं करता है।
CREATE INDEX vote_order_asc ON big_table (vote, id);
या अवरोही क्रम के लिए:
SELECT *
FROM big_table
WHERE (vote, id) < (vote_x, id_x) -- ROW values
ORDER BY vote DESC, id DESC
LIMIT n;
समान अनुक्रमणिका का उपयोग कर सकते हैं।
मेरा सुझाव है कि आप अपने कॉलम घोषित करें NOT NULL
या अपने आप को NULLS FIRST|LAST
. से परिचित कराएं निर्माण:
- डेटाटाइम एएससी द्वारा पोस्टग्रेएसक्यूएल सॉर्ट करें, पहले शून्य?
नोट दो बातें विशेष रूप से:
-
ROW
WHERE
. में मान खंड को अलग किए गए सदस्य क्षेत्रों से बदला नहीं जा सकता।WHERE (vote, id) > (vote_x, id_x)
नहीं के साथ प्रतिस्थापित किया जाए:WHERE vote >= vote_x AND id > id_xइससे सब का पता नहीं चलेगा
id <= id_x
. के साथ पंक्तियाँ , जबकि हम केवल उसी वोट के लिए ऐसा करना चाहते हैं, अगले के लिए नहीं। सही अनुवाद होगा:WHERE (vote = vote_x AND id > id_x) OR vote > vote_x
... जो इंडेक्स के साथ अच्छी तरह से नहीं चलता है, और अधिक कॉलम के लिए तेजी से जटिल हो जाता है।
एक एकल . के लिए आसान होगा कॉलम, जाहिर है। यही वह विशेष मामला है जिसका मैंने शुरुआत में उल्लेख किया था।
-
तकनीक
ORDER BY
. में मिश्रित दिशाओं के लिए काम नहीं करती है जैसे:ORDER BY vote ASC, id DESC
कम से कम मैं जेनेरिक . के बारे में नहीं सोच सकता इसे कुशलतापूर्वक लागू करने का तरीका। यदि दोनों स्तंभों में से कम से कम एक संख्यात्मक प्रकार है, तो आप
(vote, (id * -1))
पर उल्टे मान वाले कार्यात्मक अनुक्रमणिका का उपयोग कर सकते हैं - औरORDER BY
. में उसी एक्सप्रेशन का उपयोग करें :ORDER BY vote ASC, (id * -1) ASC
संबंधित:
- 'WHERE (col1, col2) <(val1, val2)' के लिए SQL सिंटैक्स शब्द
- कई तालिकाओं के स्तंभों के साथ क्रम के लिए प्रदर्शन में सुधार करें
विशेष रूप से मार्कस विनैंड I द्वारा प्रस्तुत प्रस्तुति पर ध्यान दें:
- "पेजिनेशन ने पोस्टग्रेएसक्यूएल तरीके से किया"