2012-03-07 6 views
37

पृष्ठांकन जब अपनी सामग्री रैंकिंग जल्दी से बदल सकते हैं, और भी कठिन है जब उन रैंकिंग प्रति-उपयोगकर्ता अलग कठिन है। (आइए असीमित स्क्रॉल को पेजिनेशन के प्रकार के रूप में देखें जहां लिंक अदृश्य हैं।) दो कठोर समस्याएं हैं: शीर्ष पर जोड़े गए सामग्री और पुन: संग्रहित सामग्री।क्या पेजिनेशन योजनाएं तेजी से बदलती सामग्री सूचियों को संभाल सकती हैं?

के नव-वर्द्धित सामग्री के बारे में भूल करते हैं, और स्वीकार करते हैं कि आप पेज 1 ताज़ा करने के लिए यह देखने के लिए होगा। आइए यह भी दिखाएं कि हम शुद्ध ORDER BY position कर रहे हैं; अगर आप किसी और चीज से ऑर्डर कर रहे हैं, तो आपको विंडो फ़ंक्शंस का उपयोग करना पड़ सकता है। हमारे पृष्ठों में प्रति पृष्ठ जानवरों की 4 पंक्तियां हैं। वे शुरू करते हैं:

+----+----------+-----------+ 
| id | position^| animal | 
+----+----------+-----------+ 
| 1 |  1 | Alpacas | 
| 2 |  2 | Bats  | 
| 3 |  3 | Cows  | 
| 4 |  4 | Dogs  | 
| 5 |  5 | Elephants | 
| 6 |  6 | Foxes  | 
| 7 |  7 | Giraffes | 
| 8 |  8 | Horses | 
+----+----------+-----------+ 

पृष्ठ 1 लाने के बाद, और पृष्ठ 2 लाने से पहले, बहुत सारी चीज़ें घूमती हैं। डीबी अब है:

+----+----------+-----------+ 
| id | position^| animal | 
+----+----------+-----------+ 
| 4 |  1 | Dogs  | 
| 2 |  2 | Bats  | 
| 1 |  3 | Alpacas | 
| 5 |  4 | Elephants | 
| 6 |  5 | Foxes  | 
| 7 |  6 | Giraffes | 
| 3 |  7 | Cows  | 
| 8 |  8 | Horses | 
+----+----------+-----------+ 

तीन आम तरीके हैं:

ऑफसेट/सीमा दृष्टिकोण

यह विशिष्ट अनुभवहीन दृष्टिकोण है, रेल में, यह will_paginate और Kaminari काम करता है। अगर मैं पेज 2 लेना चाहता हूं, तो मैं

SELECT * FROM animals 
ORDER BY animals.position 
OFFSET ((:page_num - 1) * :page_size) 
LIMIT :page_size; 

जो पंक्तियों 5-8 हो जाएगा। मैं हाथियों को कभी नहीं देखूंगा, और मैं गायों को दो बार देखूंगा।

अंतिम आईडी दृष्टिकोण देखा

रेडिट अलग तरीका अपनाते हैं। पृष्ठ आकार के आधार पर पहली पंक्ति की गणना करने के बजाय, ग्राहक आपके द्वारा देखी गई अंतिम वस्तु की आईडी ट्रैक करता है, जैसे बुकमार्क। जब आप "अगला" मारा, वे कहते हैं कि बुकमार्क से आगे देख शुरू:

SELECT * FROM animals 
WHERE position > (
    SELECT position FROM animals 
    WHERE id = :last_seen_id 
) 
ORDER BY position 
LIMIT :page_size; 

कुछ मामलों में, यह पेज/ऑफसेट की तुलना में बेहतर काम करता है। लेकिन हमारे मामले में, आखिरी देखी गई पोस्ट कुत्तों ने # 1 तक ज़ूम किया। तो ग्राहक ?last_seen_id=4 भेजता है, और मेरा पृष्ठ 2 बैट्स, अल्पाकास, हाथी और फॉक्स है। मैंने किसी जानवर को याद नहीं किया है, लेकिन मैंने दो बार बल्ले और अल्पाका को देखा।

सर्वर साइड राज्य

HackerNews (और हमारी साइट, अभी) सर्वर साइड निरंतरता के साथ इस को हल करती है; वे आप के लिए पूरे परिणाम सेट की दुकान (या कम से कम कई पृष्ठों?), और "अधिक" लिंक संदर्भ निरंतरता। जब मैं पेज 2 लाता हूं, तो मैं "मेरी मूल क्वेरी के पेज 2" ​​के लिए पूछता हूं। यह एक ही ऑफ़सेट/सीमा गणना का उपयोग करता है, लेकिन चूंकि यह मूल क्वेरी के खिलाफ है, इसलिए मुझे बस परवाह नहीं है कि चीजें अब घूमती हैं। मैं हाथियों, फॉक्स, Giraffes, और घोड़े देखता हूँ। कोई डुप्लिकेट नहीं, कोई मिस्ड आइटम नहीं।

नकारात्मक पक्ष यह है कि हम सर्वर पर राज्य का एक बहुत स्टोर करने के लिए होता है। HN पर, कि रैम में संग्रहित है, और वास्तव में उन निरंतरता अक्सर समय सीमा समाप्त होने से पहले आप "अधिक" बटन दबा सकते हैं, आप सभी तरह से वापस पेज 1 के मान्य लिंक को खोजने के लिए जाने के लिए मजबूर कर दिया। अधिकांश अनुप्रयोगों में, आप इसे मेमकैच में या यहां तक ​​कि डेटाबेस में भी संग्रहीत कर सकते हैं (अपनी तालिका का उपयोग करके, या ओरेकल या पोस्टग्रेएसक्यूएल में, होल्ड करने योग्य कर्सर का उपयोग करके)। आपके आवेदन के आधार पर, प्रदर्शन प्रदर्शन हो सकता है; PostgreSQL में, कम से कम, आपको सही डेटाबेस कनेक्शन को फिर से हिट करने का कोई तरीका ढूंढना होगा, जिसके लिए बहुत चिपचिपा-राज्य या कुछ चालाक बैक-एंड रूटिंग की आवश्यकता होती है।

क्या ये केवल तीन संभावित दृष्टिकोण हैं? यदि नहीं, तो क्या कंप्यूटर-विज्ञान अवधारणाएं हैं जो मुझे इस बारे में पढ़ने के लिए Google रस देगी? पूरे परिणाम सेट को संग्रहीत किए बिना निरंतरता दृष्टिकोण का अनुमान लगाने के तरीके हैं? दीर्घकालिक, जटिल घटना-स्ट्रीमिंग/पॉइंट-इन-टाइम सिस्टम है, जहां "पेज 1 लाए गए पल के परिणामस्वरूप परिणाम" हमेशा के लिए व्यर्थ है। उस से कम ...?

+1

मैं इसे एक अलग कोण से देखने का सुझाव दूंगा। हो सकता है कि पेजिनेशन से बचने के लिए संभव है- केवल अनंत स्क्रॉल का उपयोग करें + कुछ व्यापक स्क्रिप्टिंग जो पेज रीलोड के बिना अपडेट सूची और उचित प्रदर्शित करता है ↑/↓ उपयोगकर्ता सुविधा के लिए प्रतीकों। यह आपके उपयोग के मामले पर निर्भर करता है, हालांकि। अपडेट किया गया: एफडब्ल्यूआईडब्ल्यू, यहां [एक संबंधित प्रश्न] है (http://ux.stackexchange.com/questions/2997/best-way-to-add-items-to-a-paginated-list/2999#2999) यूएक्स स्टैक एक्सचेंज से । – Tony

+0

हाँ, यह हमारे उपयोग के मामले के लिए काम नहीं करता है ... चीजें लगातार पुन: क्रमबद्ध होती हैं, और आप नहीं चाहते कि डिस्प्ले लगातार अद्यतन हो। महान विचार, यद्यपि। –

+0

आप क्लाइंट पर राज्य स्टोर कर सकते हैं, और देखे गए रिकॉर्ड के सभी आईडी भेज सकते हैं। –

उत्तर

2

हम अब सर्वर-साइड स्टेट दृष्टिकोण के साथ जा रहे हैं, पहले परिणाम पर पूरे परिणाम को कैशिंग करते हैं, इसलिए हम हमेशा एक सतत सूची लौटाते हैं। यह तब तक काम करेगा जब तक हमारी क्वेरी पहले से ही सभी पंक्तियों को वापस न करे; आखिरकार हमें निकटतम पड़ोसी दृष्टिकोण का उपयोग करने की आवश्यकता होगी और वह काम नहीं करेगा।

लेकिन मुझे लगता है कि एक चौथाई संभावना है, जो बहुत अच्छी तरह से अनुरूप है, जब तक है:

  1. आप एक गारंटी नहीं डुप्लिकेट की जरूरत नहीं है, केवल एक उच्च संभावना
  2. तुम ओ ग्राहक नहीं रख लो: स्क्रॉल के दौरान कुछ सामग्री लापता, जब तक आप डुप्लिकेट

समाधान से बचने के रूप में के साथ ठीक "पिछली बार आईडी" समाधान का एक प्रकार है ne, लेकिन 5 या 10 या 20 बुकमार्क - कुछ पर्याप्त है कि आप उन्हें कुशलता से स्टोर कर सकते हैं।

SELECT * FROM posts 
WHERE id > :bookmark_1 
AND id > :bookmark_2 
... 
ORDER BY id 

बुकमार्क की संख्या विकसित होता है, बाधाओं तेजी से (क) पिछले सभी n बुकमार्क कुछ बिंदु पर शुरू होने वाले लेकिन (ख) वैसे भी डुप्लिकेट सामग्री को देखने, क्योंकि वे कम है कि आप कर रहे हैं: क्वेरी की तरह लग रही समाप्त होता है सभी reranked थे।

यदि भविष्य में छेद हैं, या बेहतर उत्तर हैं, तो मैं खुशी से इस उत्तर को अस्वीकार कर दूंगा।

4

ओरेकल इस अच्छी तरह से संभालता है। जब तक एक कर्सर खुला रहता है, आप जितनी बार आवश्यक हो उतना बार ला सकते हैं और आपके परिणाम हमेशा उस बिंदु को प्रतिबिंबित करेंगे जब कर्सर खोला गया था। यह पूर्ववत लॉग से डेटा का उपयोग कर्सर खोले जाने के बाद किए गए वर्चुअल रोलबैक परिवर्तनों में करता है।

यह तब तक काम करेगा जब तक आवश्यक रोलबैक डेटा अभी भी उपलब्ध न हो। आखिर में लॉग का पुनर्नवीनीकरण हो जाता है और रोलबैक डेटा अब उपलब्ध नहीं है, इसलिए लॉग स्पेस, सिस्टम गतिविधि इत्यादि के आधार पर कुछ सीमा है

दुर्भाग्यवश (आईएमओ), मुझे किसी भी अन्य डीबी के बारे में पता नहीं है इस तरह काम करता है। अन्य डेटाबेस जिन्हें मैंने रीड-स्थिरता सुनिश्चित करने के लिए उपयोग ताले के साथ काम किया है, जो समस्याग्रस्त है यदि आप बहुत कम अवधि से अधिक स्थिरता पढ़ना चाहते हैं।

+1

बाहर निकलता है PostgreSQL में होल्ड करने योग्य कर्सर भी हैं। ओरेकल पर, क्या आप उस कर्सर को एक अलग कनेक्शन, दास इत्यादि से मार सकते हैं? PostgreSQL होल्ड करने योग्य कर्सर डिस्क-आधारित हैं (इसलिए आप रैम चबाने नहीं कर रहे हैं) और वे लेनदेन लॉग भी काम करते हैं, लेकिन वे केवल उसी कनेक्शन पर उपलब्ध हैं, इसलिए आपको चिपचिपापन सुनिश्चित करना होगा या कुछ बैक-एंड रूटिंग करना होगा । –

5

समाधान 1: "hacky समाधान"

एक समाधान पहले ही देख चुके सामग्री, एक उदाहरण के लिए आईडी की सूची के अपने ग्राहक रखने ट्रैक में शामिल कर सकता है। प्रत्येक बार जब आपको किसी अन्य पृष्ठ की आवश्यकता होती है, तो आप इस आईडी सूची को अपने सर्वर कॉल के पैरामीटर में जोड़ते हैं। आपका सर्वर सामग्री का ऑर्डर कर सकता है, पहले से देखी गई सामग्री को हटा सकता है और सही पृष्ठ प्राप्त करने के लिए ऑफ़सेट लागू कर सकता है।

मैं इसकी अनुशंसा नहीं करता हूं और मैं हैकी पर जोर देता हूं। मैं इसे यहां लिखता हूं क्योंकि यह तेज़ है और कुछ जरूरतों के साथ फिट हो सकता है।यहां उन बुरी चीजें हैं जिनके बारे में मैं सोच सकता हूं:

1) इसे सही करने के लिए क्लाइंट पक्ष पर कुछ काम की ज़रूरत है (ऊपर दिए गए वाक्य में "पहले से देखा गया" का अर्थ क्या है, यदि मैं पिछले पृष्ठ पर जाता हूं तो क्या होगा?)

2) परिणामस्वरूप आदेश आपकी सच्ची आदेश नीति को प्रतिबिंबित नहीं करता है। एक सामग्री को पृष्ठ 2 में प्रदर्शित किया जा सकता है हालांकि नीति को इसे पृष्ठ 1 पर रखना चाहिए था। इससे उपयोगकर्ता की गलतफहमी हो सकती है। आइए अपनी पूर्व ऑर्डरिंग पॉलिसी के साथ स्टैक ओवरफ़्लो का उदाहरण लें, जिसका अर्थ है कि पहले सबसे ऊपर जवाब दिए गए हैं। हमारे पास पेज 2 में 6 अपवॉट्स के साथ एक प्रश्न हो सकता है जबकि 4 अपवॉट्स के साथ एक प्रश्न पृष्ठ 1 में होगा। ऐसा तब होता है जब 2 या अधिक अपवॉट होते हैं जबकि उपयोगकर्ता पृष्ठ 1 पर था। -> उपयोगकर्ता के लिए आश्चर्यजनक हो सकता है ।

समाधान 2: "ग्राहक समाधान"

यह मूल रूप से एक आप "सर्वर-साइड स्थिति" कॉल करने के लिए क्लाइंट साइड बराबर समाधान है। यह तब उपयोगी होता है जब सर्वर पक्ष पर पूर्ण क्रम का ट्रैक रखना पर्याप्त सुविधाजनक नहीं है। यह काम करता है अगर आइटम सूची अनंत नहीं है।

  • यह सहेजें क्लाइंट पक्ष
  • सीधे अपनी सामग्री के आईडी के माध्यम से आइटम को पुनः प्राप्त पर पूर्ण (परिमित) क्रम सूची + आइटम्स की संख्या/पेज
  • प्राप्त करने के लिए अपने सर्वर पर कॉल करें।
1

पार्टी के लिए बहुत देर हो चुकी है लेकिन यहां कुछ ऐसा है जिसका हमने प्रयोग किया था। हम निरंतर लोडिंग का उपयोग कर रहे हैं, न कि पृष्ठ जो उपयोगकर्ता आगे और आगे जाते हैं।

ग्राहक सभी आईडी यह प्रदर्शित किया है की एक सूची बनाता है, इसलिए पहले सेट के बाद यह हो सकता है: 4,7,19,2,1,72,3

हम और अधिक सामग्री लोड जब हम एक ही प्रकार के साथ एक ही प्रश्न करें, लेकिन इसे इसमें जोड़ें: जहां आईडी नहीं है (4,7,19,2,1,72,3)

सूची में नहीं बल्कि तेजी से बढ़ सकता है। हमारे लिए यह कोई मुद्दा नहीं है क्योंकि हमारे आंतरिक उपकरण में आमतौर पर बहुत से परिणाम नहीं होते हैं।

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

संबंधित मुद्दे