एक क्वेरी में MySQL ORDER BY और LIMIT को कैसे संसाधित करता है?


251

मेरे पास एक क्वेरी है जो इस तरह दिखती है:

SELECT article FROM table1 ORDER BY publish_date LIMIT 20

ORDER BY कैसे काम करता है? क्या यह सभी रिकॉर्डों का आदेश देगा, फिर पहले 20 प्राप्त करेगा, या यह 20 रिकॉर्ड प्राप्त करेगा और उन्हें publish_dateक्षेत्र द्वारा आदेश देगा ?

यदि यह अंतिम है, तो आपको वास्तव में सबसे हाल के 20 लेख प्राप्त करने की गारंटी नहीं है।


6
ध्यान दें कि यदि कुछ publish_dates समान हैं, तो उनके द्वारा आदेश देना निर्धारित परिणाम नहीं देता है, जिसका अर्थ है कि यदि आप LIMITपृष्ठांकन के लिए उपयोग करते हैं, तो आप अलग-अलग पृष्ठों पर समान आइटम प्राप्त कर सकते हैं!
कोनराड मोरावस्की

जवाबों:


245

यह पहले ऑर्डर करेगा, फिर पहले 20 प्राप्त करेगा। एक डेटाबेस पहले भी WHEREक्लॉज में कुछ भी प्रोसेस करेगा ORDER BY


1
तो समय समान है?
यासर अराफात

7
गलत! LIMITटूट जाता है ORDER BY। साथ LIMITएक ORDER BYरिटर्न गलत परिणाम। LIMITकिसी भी तरह से रिजल्ट सेट को फिर से शुरू किया गयाORDER BY
ग्रीन

6
@ग्रीन, तुम गलत हो। स्पष्टीकरण के लिए इसे पढ़ें: dev.mysql.com/doc/refman/5.7/en/limit-optimization.html जब ORDER BY कॉलम को अनुक्रमित किया जाता है, तो यह बिना किसी भिन्न सीमा के, एक अलग क्रम में रिकॉर्ड वापस कर सकता है, जब अधिक हो उस कॉलम में समान मान के साथ 1 से अधिक रिकॉर्ड।
yitwail

1
इस तरह की समस्याओं का एक त्वरित समाधान यह है कि अधिमानतः अद्वितीय मान रखने के लिए एक और कॉलम जोड़ा जाए ताकि डेटाबेस को पंक्तियों को ऑर्डर करने के लिए एक सुसंगत नियम मिल जाए जब पहला ऑर्डर-बाय-कॉलम का मूल्य कई पंक्तियों के लिए समान हो।
rineez

37

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

दो तर्कों के साथ, पहला तर्क वापसी के लिए पहली पंक्ति की भरपाई को निर्दिष्ट करता है, और दूसरा वापस लौटने के लिए पंक्तियों की अधिकतम संख्या को निर्दिष्ट करता है। प्रारंभिक पंक्ति की ऑफसेट 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 के बराबर है।

सभी विवरण: http://dev.mysql.com/doc/refman/5.0/en/select.html


क्या यह 5-14 पंक्तियों को पुनः प्राप्त नहीं करता है?
एडोनिस के। काकोलीडिस

@adonis नहीं, यह नहीं है। उदाहरण MySQL प्रलेखन
dcaswell

5 नंबर 6 वीं पंक्ति है। 5 पंक्तियों (0 के माध्यम से 4) की अनदेखी की जाती है।
फिल पेरी

1
लेकिन आदेश के बिना लिमिट का उपयोग करना असंगत परिणाम दे सकता है! दुर्भाग्य से, पूरे परिणाम सेट को लिमिट लागू होने से पहले आदेश दिया जाना चाहिए या डीबीएमएस मनमाने ढंग से परिणाम का आदेश देने के लिए स्वतंत्र है और फिर उस सेट पर ओएफएसईटीटी और लिमिट। मैंने पढ़ा है कि यह DBMS OFFSET और LIMIT के आधार पर एक वैकल्पिक क्वेरी योजना का चयन करने के कारण हो सकता है, इस प्रकार मनमाना आदेश।
बार्टन

4
सवाल सीमा और आदेश पूछ रहा है। लेकिन जवाब इस सवाल से संबंधित नहीं है
शेन लिआंग

9

जैसा कि @ जेम्स कहते हैं, यह सभी रिकॉर्डों का आदेश देगा, फिर पहले 20 पंक्तियों को प्राप्त करें।

जैसा कि ऐसा है, आपको 20 पहले प्रकाशित लेख प्राप्त करने की गारंटी है, नए नहीं दिखाए जाएंगे।

अपनी स्थिति में, मुझे लगता है कि आप जोड़ने की सलाह देते descकरने के लिए order by publish_date, यदि आप नवीनतम लेख चाहते हैं, तो नवीनतम लेख पहली बार किया जाएगा।

यदि आपको परिणाम को बढ़ते क्रम में रखने की आवश्यकता है, और अभी भी केवल 10 नवीनतम लेख चाहते हैं तो आप mysql को दो बार अपना परिणाम सॉर्ट करने के लिए कह सकते हैं।

नीचे दी गई यह क्वेरी परिणाम को नीचे लाएगी और परिणाम को 10 तक सीमित कर देगी (जो कि कोष्ठक के अंदर क्वेरी है)। यह अभी भी अवरोही क्रम में क्रमबद्ध होगा, और हम इससे संतुष्ट नहीं हैं, इसलिए हम mysql को इसे और अधिक समय तक क्रमबद्ध करने के लिए कहते हैं। अब हमारे पास अंतिम पंक्ति पर नवीनतम परिणाम है।

select t.article 
from 
    (select article, publish_date 
     from table1
     order by publish_date desc limit 10) t 

order by t.publish_date asc;

यदि आपको सभी स्तंभों की आवश्यकता है, तो यह इस प्रकार किया जाता है:

select t.* 
from 
    (select * 
     from table1  
     order by publish_date desc limit 10) t 

order by t.publish_date asc;

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


2
आपकी अतिरिक्त छँटाई वस्तुतः प्रदर्शन पर कोई औसत दर्जे का प्रभाव नहीं डाल सकती है क्योंकि यह केवल 10 पंक्तियों / वस्तुओं तक ही सीमित है :-)। आम तौर पर एक इन-मेमोरी टेबल (जो एक उप-चयन का उत्पादन होता है) को छांटने में बहुत तेज और बमुश्किल औसत दर्जे का होता है जब तक कि आपके पास लाखों पंक्तियाँ नहीं होती या DBMS परिणाम को डिस्क पर सेट कर रहा होता है क्योंकि यह मेमोरी में फिट नहीं होता है (किन मामलों में DBMS के आधार पर यह क्वेरी को निरस्त भी कर सकता है)।
मार्टिन केर्स्टन

7

यदि publish_dateफ़ील्ड पर इस मामले में एक उपयुक्त सूचकांक है, तो MySQL को 20 रिकॉर्ड किए गए अनुरोधों को प्राप्त करने के लिए पूरे सूचकांक को स्कैन करने की आवश्यकता नहीं है - सूचकांक के शुरू में 20 रिकॉर्ड मिलेंगे। लेकिन अगर कोई उपयुक्त सूचकांक नहीं है, तो तालिका की एक पूर्ण स्कैन की आवश्यकता होगी।

इस पर 2009 से एक MySQL प्रदर्शन ब्लॉग लेख है।


7

आप जल्द से जल्द या नवीनतम रिकॉर्ड प्राप्त करने के लिए आदेश के अंत में [asc] या [desc] जोड़ सकते हैं

उदाहरण के लिए, यह आपको पहले नवीनतम रिकॉर्ड देगा

ORDER BY stamp DESC

LIMITबाद में क्लॉज अप्लाई करेंORDER BY


3
Stackoverflow में आपका स्वागत है। मुझे लगता है कि आपने सवाल गलत समझा हो सकता है। मेरा मानना ​​है कि वे "क्रमबद्ध कैसे करें" के बजाय संचालन के क्रम के बारे में पूछ रहे थे। (लेकिन यह कुछ समय पहले ही प्रश्न का उत्तर देने के बाद से ही
लूट है

5

आप इस कोड का उपयोग कर सकते हैं SELECT article FROM table1 ORDER BY publish_date LIMIT 0,10 जहां 0 रिकॉर्ड की एक प्रारंभिक सीमा है और रिकॉर्ड की 10 संख्या है


8
नहीं, यह आवश्यक नहीं हैLIMIT 10के लिए आशुलिपि है LIMIT 0,10
लॉरेंस डोल

2
हाँ, सीमा ०,१० के लिए आवश्यक नहीं है, लेकिन आप इस सीमा को १०,२० की तरह कर सकते हैं
गौरांगथिरिया

3

लिमिट को आमतौर पर अंतिम ऑपरेशन के रूप में लागू किया जाता है, इसलिए परिणाम पहले छांटा जाएगा और फिर 20 तक सीमित किया जाएगा। वास्तव में, पहले 20 छंटे हुए परिणाम मिलते ही छंटनी बंद हो जाएगी।


11
आपका दूसरा वाक्य आपके पहले के खिलाफ जाता है। जब पहले 20 परिणाम मिलते हैं तो छंटनी बंद नहीं हो सकती क्योंकि जैसा कि आपने कहा कि परिणाम वापस आने से पहले छंटाई की जाएगी। MySQL केवल यह जान सकता है कि छँटाई समाप्त होने के बाद पहले 20 परिणाम क्या हैं।
टॉम

@, वास्तव में, यदि यह अनुक्रमित कॉलम द्वारा आदेश दे सकता है। इसे यहाँ समझाया गया है: dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
yitwail

-3

डेटाबेस के अनुसार भी LIMIT का सिंटैक्स अलग है:

mysql - सीमा 1, 2

postgres - सीमा 2 OFFSET 1

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.