MySQL डेटा - पेजिंग को लागू करने का सबसे अच्छा तरीका?


208

मेरा iPhone ऐप MySQL डेटाबेस से डेटा पुनः प्राप्त करने के लिए मेरी PHP वेब सेवा से जुड़ता है। एक अनुरोध 500 परिणाम वापस कर सकता है।

पेजिंग को लागू करने और एक बार में 20 आइटम पुनर्प्राप्त करने का सबसे अच्छा तरीका क्या है?

मान लीजिए कि मुझे अपने डेटाबेस से पहले 20 विज्ञापन मिले हैं। अब मैं अगले 20 विज्ञापनों के लिए कैसे अनुरोध कर सकता हूं?

जवाबों:


309

MySQL प्रलेखन से :

लिमिट क्लॉज का उपयोग सेलेक्ट स्टेटमेंट द्वारा दी गई पंक्तियों की संख्या को बाधित करने के लिए किया जा सकता है। लिमिट एक या दो संख्यात्मक तर्क लेता है, जिसमें दोनों को गैर-पूर्णांक स्थिरांक स्थिरांक होना चाहिए (तैयार किए गए बयानों का उपयोग करते समय छोड़कर)।

दो तर्कों के साथ, पहला तर्क वापस लौटने के लिए पहली पंक्ति के ऑफसेट को निर्दिष्ट करता है, और दूसरा अधिकतम पंक्तियों को वापस लौटने के लिए निर्दिष्ट करता है। प्रारंभिक पंक्ति की ऑफसेट 0 है (1 नहीं):

SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15

परिणाम सेट के अंत तक एक निश्चित ऑफसेट से सभी पंक्तियों को पुनः प्राप्त करने के लिए, आप दूसरे पैरामीटर के लिए कुछ बड़ी संख्या का उपयोग कर सकते हैं। यह कथन 96 वीं पंक्ति से अंतिम तक सभी पंक्तियों को पुनः प्राप्त करता है:

SELECT * FROM tbl LIMIT 95,18446744073709551615;

एक तर्क के साथ, मान परिणाम सेट की शुरुआत से लौटने के लिए पंक्तियों की संख्या निर्दिष्ट करता है:

SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows

दूसरे शब्दों में, LIMIT row_count LIMIT 0, row_count के बराबर है।


107
पेजिंग के लिए LIMIT का उपयोग करते समय आपको एक ORDER BY भी निर्दिष्ट करना चाहिए।
मार्क बायर्स

10
@ शील: प्रलेखन के हवाले से कुछ भी गलत नहीं है, लेकिन मैं मानता हूं कि उसे इस बात का उल्लेख करना चाहिए कि वह डॉक्स की नकल कर रहा है और मूल स्रोत के लिए एक लिंक प्रदान किया है। इसके अलावा, मुझे आश्चर्य है कि प्रलेखन में ORDER BY के बिना LIMIT का उपयोग करने के उदाहरण शामिल होंगे ... जो उत्साहजनक होने के लिए एक बुरे अभ्यास की तरह लगता है। आदेश के बिना कोई गारंटी नहीं है कि आदेश कॉल के बीच समान होगा।
मार्क बायर्स

13
वैसे भी, जब बड़े परिणामों को पृष्ठांकित किया जाता है (और यही पृष्ठांकन के लिए है - बड़े परिणाम को छोटे हिस्से में तोड़ें, तो सही?), आपको ध्यान रखना चाहिए कि यदि आप एक करते हैं limit X, Y, तो अनिवार्य रूप से क्या होता है कि X + Y पंक्तियों को पुनः प्राप्त किया जाता है और फिर? शुरुआत से एक्स पंक्तियों को गिरा दिया जाता है और जो कुछ भी छोड़ दिया जाता है वह वापस आ जाता है दोहराए जाने के लिए: limit X, YX + Y पंक्तियों के स्कैन में परिणाम।
शीलेंट

7
मुझे आपका LIMIT 95, 18446744073709551615 विचार पसंद नहीं है .. OFFSET;-) पर एक नज़र डालें;
चार्ल्सलेफ़

5
बड़े डेटा के साथ काम करते समय यह कुशल नहीं है। चेचक के लिए cular.com/implementing-pagination तरीके की जाँच करें , जो विशिष्ट scenerio के लिए उपयुक्त हैं।
अमित

125

500 रिकॉर्ड के लिए दक्षता शायद एक मुद्दा नहीं है, लेकिन अगर आपके पास लाखों रिकॉर्ड हैं तो अगले पृष्ठ का चयन करने के लिए WHERE क्लॉज का उपयोग करना फायदेमंद हो सकता है:

SELECT *
FROM yourtable
WHERE id > 234374
ORDER BY id
LIMIT 20

"234374" यहां आपके द्वारा देखे गए प्रचलित पृष्ठ से अंतिम रिकॉर्ड की आईडी है।

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

इस दृष्टिकोण का एक और लाभ यह है कि यदि कॉल के बीच डेटा बदल जाता है तो आप रिकॉर्ड को याद नहीं करेंगे या दोहराया रिकॉर्ड नहीं पाएंगे। ऐसा इसलिए है क्योंकि किसी पंक्ति को जोड़ने या हटाने का अर्थ है कि परिवर्तन के बाद सभी पंक्तियों की भरपाई। आपके मामले में यह संभवतः महत्वपूर्ण नहीं है - मुझे लगता है कि आपके विज्ञापनों का पूल बहुत बार नहीं बदलता है और वैसे भी कोई भी नोटिस नहीं करेगा कि क्या वे एक ही विज्ञापन को लगातार दो बार प्राप्त करते हैं - लेकिन यदि आप "सबसे अच्छे तरीके" की तलाश में हैं तब यह एक और बात ध्यान में रखना है कि किस दृष्टिकोण का उपयोग करना है।

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


1
यह इस तरह से अधिक है: पी जबकि मैं निहितार्थ को पूरी तरह से अस्वीकार करता हूं, कि 'नए' आईडी हमेशा बड़े होते हैं, 'पुराने' की तुलना में, अधिकांश समय यह वास्तव में मामला होगा और इसलिए, मुझे लगता है, यह 'अच्छा' है बस'। वैसे भी, हाँ, जैसा कि आपने प्रदर्शित किया, उचित पृष्ठांकन (बड़े परिणाम पर गंभीर प्रदर्शन में गिरावट के बिना) विशेष रूप से तुच्छ और लेखन नहीं है limit 1000000, 10और उम्मीद है कि यह आपको कहीं भी नहीं मिलेगा।
शील्ट

1
देर से देखने का लिंक बहुत उपयोगी है
pvgoddijn

1
यदि आप सिर्फ आईडी ऑर्डर के लिए "DESC" का उपयोग करते हैं तो यह पृष्ठांकन पीछे की ओर काम करता है। मुझें यह पसंद है!
डेनिस हेडेन

2
लेकिन कितनी बार लोग वास्तविक दुनिया में "डेट क्रिएट" करके, आईडी द्वारा या इन्सिनिशन द्वारा ऑर्डर करना चाहते हैं?
रिचीएचएच

अच्छी पोस्ट, लेकिन area=width*heightइसलिए यह केवल रिकॉर्ड की मात्रा नहीं है जो मायने रखती है, लेकिन प्रत्येक रिकॉर्ड का आकार भी एक कारक है जब स्मृति में परिणाम जमा करते हैं
कुछ

43

क्वेरी के लिए OFFSET को परिभाषित करें । उदाहरण के लिए

पृष्ठ 1 - (रिकॉर्ड 01-10): ऑफसेट = 0, सीमा = 10;

पृष्ठ 2 - (रिकॉर्ड 11-20) ऑफसेट = 10, सीमा = 10;

और निम्नलिखित प्रश्न का उपयोग करें:

SELECT column FROM table LIMIT {someLimit} OFFSET {someOffset};

पेज 2 के लिए उदाहरण:

SELECT column FROM table
LIMIT 10 OFFSET 10;

1
क्या आपको पेज -2 के लिए ऑफसेट = 10 का मतलब नहीं है?
जेनना मायज

28

इसके बारे में साहित्य है:

मुख्य समस्या बड़े OFFSETएस के उपयोग के साथ होती है । वे OFFSETकई तरह की तकनीकों का उपयोग करने से बचते हैं , जो idश्रेणी के चयन से लेकर WHERE, किसी प्रकार के कैशिंग या प्री-कंप्यूटिंग पेज तक हैं।

उपयोग INDEX, ल्यूक में सुझाए गए समाधान हैं :


1
जटिल प्रश्नों के प्रत्येक पेजिंग क्वेरी के लिए अधिकतम आईडी प्राप्त करने का परिणाम गैर-व्यावहारिक होगा, गैर-उत्पादन उपयोग रैंक, पंक्ति संख्या और पेजिंग के प्रकार के बीच पेजिंग में मदद करता है!
रिजवान पटेल

उस रणनीति को ध्यान में रखा गया है और प्रदान की गई कड़ियों में उचित मूल्यांकन किया गया है। यह इतना आसान नहीं है।
लुचोस्तिन

प्रदान की गई लिंक केवल बेस पिवट यूनी-पिवट, क्रॉस अप्लाई, मल्टी सीटीई या व्युत्पन्न टेबल मैकेनिक्स को पूरा करने के लिए लगती है? फिर से मैं अपने मामले को ऐसे परिमाण पर पुनर्लेखन प्रश्नों के साथ फिर से खड़ा करता हूं ताकि अधिकतम प्राप्त करने के लिए फिर से वास्तुशिल्प ओवरकिल हो! और फिर क्रमबद्धता के साथ n "कॉलम की संख्या के लिए फिर से क्रमपरिवर्तन और संयोजन!
रिज़वान पटेल

1
क्या मैं गलत समझ रहा हूं कि "पेजिनेशन ने सही तरीके से किया है" लिंक, या क्या यह किसी भी क्वेरी में अव्यवहारिक है जिसमें फ़िल्टरिंग शामिल है।
contactmatt

1
@ कॉन्टेक्टमैट मैं आपका गुस्सा साझा करता हूं। अंत में, ऐसा लगता है कि कुशलतापूर्वक पूर्ण आवश्यकता को लागू करने का कोई तरीका नहीं है, लेकिन मूल के चारों ओर आराम से विविधताएं हैं।
ल्यूकोस्टीन

13

यह ट्यूटोरियल पेजिंग करने का एक शानदार तरीका दिखाता है। माईएसक्यूएल का उपयोग करके कुशल पृष्ठांकन

संक्षेप में, OFFSET या बड़े सीमा का उपयोग करने से बचें


24
शायद एक सारांश दे?
एंड्रयू

हाँ, मैं उत्तर में अधिक प्रयास की सराहना करूंगा।
जर्काइंड

6

आप भी कर सकते हैं

SELECT SQL_CALC_FOUND_ROWS * FROM tbl limit 0, 20

चयनित स्टेटमेंट की पंक्ति गणना (सीमा के बिना) उसी चयन स्टेटमेंट में कैप्चर की जाती है, ताकि आपको टेबल के आकार को फिर से क्वेरी करने की आवश्यकता न हो। आपको SELUND FOUND_ROWS () का उपयोग करके पंक्ति गणना मिलती है;


1
यह विशेष रूप से अक्षम है। *अधिक स्तंभों से आवश्यक किया जा रहा है दिलवाया, और में परिणाम SQL_CALC_FOUND_ROWSउन स्तंभों में परिणामों से पढ़ा जा रहा सब तालिका में पंक्तियों, भले ही वे परिणाम में शामिल नहीं हैं। यह एक अलग क्वेरी में पंक्तियों की संख्या की गणना करने के लिए बहुत अधिक कुशल होगा जो उन सभी कॉलमों को नहीं पढ़ता है। फिर आपकी मुख्य क्वेरी 20 पंक्तियों को पढ़ने के बाद बंद हो सकती है।
7

क्या आपको यकीन है? मैंने एक बड़ी तालिका SQL_CALC_FOUND_ROWS और किसी अन्य क्वेरी का उपयोग नहीं करने के खिलाफ क्वेरी समयबद्ध की। मैंने कोई समय अंतर नहीं देखा। किसी भी तरह से यह 2 प्रश्न करने से तेज है। 1 - का चयन करें * atable सीमा 0 20 से, और फिर atable से गिनती (*) का चयन करें।
सुरज

1
हाँ मुझे यकीन है - यहाँ अधिक जानकारी है । सभी मामलों में जब आप पंक्तियों को फ़िल्टर करने के लिए एक सूचकांक का उपयोग कर रहे हैं, SQL_CALC_FOUND_ROWS 2 अलग-अलग प्रश्न करने की तुलना में काफी धीमा है। दुर्लभ अवसर पर आप किसी इंडेक्स का उपयोग नहीं कर रहे हैं, या (इस सरलीकृत उदाहरण में) आपके पास कोई क्लॉज नहीं है और यह एक MYISAM टेबल है, इससे थोड़ा अंतर पड़ता है (यह उसी गति के आसपास है)।
thomasrutter

इसके अलावा यहाँ Stackoverflow पर इसके बारे में
thomasrutter

4

क्वेरी 1: SELECT * FROM yourtable WHERE id > 0 ORDER BY id LIMIT 500

क्वेरी 2: SELECT * FROM tbl LIMIT 0,500;

क्वेरी 1 छोटे या मध्यम रिकॉर्ड के साथ तेजी से चलती है, यदि रिकॉर्ड की संख्या 5,000 या उससे अधिक है, तो परिणाम समान हैं।

500 रिकॉर्ड के लिए परिणाम:

Query1 9.9999904632568 मिलीसेकंड ले

Query2 19.999980926514 मिलीसेकंड ले

8,000 रिकॉर्ड के लिए परिणाम:

Query1 129.99987602234 मिलीसेकंड ले

Query2 160.00008583069 मिलीसेकंड ले


आपको एक इंडेक्स डालने की आवश्यकता है id
Maarten

6
कैसे id > 0उपयोगी है?
मिशेल जुंग

1
जैसा कि मैर्टन ने कहा, वे दो प्रश्न मौलिक रूप से एक जैसे दिखाई देते हैं, और संभवत: उसी तरह से टूट जाते हैं, जैसे मशीन-स्तर कमांड। आपको अनुक्रमण समस्या या MySQL का वास्तव में पुराना संस्करण होना चाहिए।
होल्डऑफहुंगर

धन्यवाद, जैसा कि मैंने आपके उत्तर को नहीं देखा, मुझे केवल उस क्रम को देखने की आवश्यकता है जिसमें आदेश, सीमा और सीमा आती है
श्रेया मेहता

गलत उदाहरण का उपयोग किया गया है। साथ मेंoffset (सीमा के पहले तर्क ऑफसेट है), तब भी आप सीमित करने के लिए सभी डेटा का चयन कर रहे है, तो भरपाई की उस राशि को त्यागकर, तो खंड जो बीच में है लौटने offsetऔर limitwhereदूसरी ओर खंड के साथ , आप ONLYउस विशिष्ट भाग को क्वेरी और क्वेरी के लिए एक तरह का प्रारंभ बिंदु निर्धारित कर रहे हैं ।
सेप्स

0

पेजिंग एकल तालिका से डेटा लाने पर सरल है, लेकिन जब यह डेटा को कई तालिकाओं में शामिल करता है, तो यह जटिल है। यहाँ MySql और स्प्रिंग के साथ एक अच्छा उदाहरण है:
https://www.easycodeforall.com/zpagination1.jsp


कृपया एक दिन गायब होने वाले तृतीय पक्ष साइटों के लिंक साझा न करें। यदि आप लेखकों के प्रश्न का उत्तर देना चाहते हैं, तो उनकी सहायता के लिए संबंधित कोड पोस्ट करें।
अनब्रांडेड मैनचेस्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.