MySQL ประมวลผล ORDER BY และ LIMIT ในแบบสอบถามอย่างไร


251

ฉันมีคำถามที่มีลักษณะเช่นนี้:

SELECT article FROM table1 ORDER BY publish_date LIMIT 20

ORDER BY ทำงานอย่างไร มันจะเรียงลำดับระเบียนทั้งหมดแล้วรับ 20 อันดับแรกหรือจะได้รับ 20 รายการและสั่งซื้อจากpublish_dateเขตข้อมูลหรือไม่

หากเป็นรายการสุดท้ายคุณไม่รับประกันว่าจะได้รับ 20 บทความล่าสุด


6
โปรดทราบว่าหากบางอันpublish_dateมีค่าเท่ากันการเรียงลำดับโดยพวกเขาจะไม่ให้ผลลัพธ์ที่แน่นอนซึ่งหมายความว่าหากคุณใช้LIMITการแบ่งหน้าคุณอาจจบลงด้วยการได้รับไอเท็มเดียวกันในหน้าต่างๆ!
Konrad Morawski

คำตอบ:


245

มันจะสั่งซื้อครั้งแรกแล้วได้รับครั้งแรก 20. ฐานข้อมูลนอกจากนี้ยังจะดำเนินการอะไรในประโยคก่อนWHEREORDER BY


1
ดังนั้นเวลาจะเหมือนกันหรือไม่
Yasar Arafath

7
ไม่ถูกต้อง! แบ่งLIMIT ORDER BYด้วยผลตอบแทนที่ไม่ถูกต้อง จัดลำดับใหม่ชุดผลลัพธ์ที่ส่งคืนโดยLIMITORDER BYLIMITORDER BY
กรีน

6
@ กรีนคุณเข้าใจผิด อ่านสิ่งนี้สำหรับคำอธิบาย: dev.mysql.com/doc/refman/5.7/en/limit-optimization.htmlเมื่อมีการทำดัชนีคอลัมน์ ORDER BY คอลัมน์มันอาจส่งคืนระเบียนในลำดับที่แตกต่างจากไม่มี LIMIT เมื่อมีมากกว่า มากกว่า 1 ระเบียนที่มีค่าเดียวกันในคอลัมน์นั้น
yitwail

1
วิธีแก้ปัญหาอย่างรวดเร็วหนึ่งอย่างสำหรับปัญหาดังกล่าวคือการเพิ่มคอลัมน์อีกหนึ่งคอลัมน์เพื่อจัดเรียงโดยควรมีค่าที่ไม่ซ้ำกันเพื่อให้ฐานข้อมูลได้รับกฎที่สอดคล้องกันสำหรับการสั่งซื้อแถวเมื่อค่าของคอลัมน์ลำดับแรกเป็นคอลัมน์เดียวกัน
rineez

37

ส่วนคำสั่ง LIMIT สามารถใช้เพื่อ จำกัด จำนวนแถวที่ส่งคืนโดยคำสั่ง SELECT LIMIT รับอาร์กิวเมนต์หนึ่งหรือสองอาร์กิวเมนต์ซึ่งทั้งคู่ต้องเป็นค่าคงที่จำนวนเต็มแบบไม่ลบ (ยกเว้นเมื่อใช้คำสั่งที่เตรียมไว้)

ด้วยสองข้อโต้แย้งอาร์กิวเมนต์แรกจะระบุการชดเชยของแถวแรกที่จะกลับมาและที่สองระบุจำนวนแถวสูงสุดที่จะกลับมา ออฟเซ็ตของแถวแรกคือ 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 K. Kakoulidis

@adonis ไม่มันไม่ใช่ ตัวอย่างนี้ถูกต้องจากเอกสาร MySQL
dcaswell

หมายเลข 5 คือแถวที่ 6 5 แถว (0 ถึง 4) จะถูกละเว้น
Phil Perry

1
แต่การใช้ LIMIT โดยไม่มีคำสั่งซื้ออาจให้ผลลัพธ์ที่ไม่สอดคล้องกัน! น่าเสียดายที่ต้องมีการสั่งซื้อชุดผลลัพธ์ทั้งหมดก่อนที่จะใช้ LIMIT หรือ DBMS มีอิสระในการสั่งซื้อผลลัพธ์โดยพลการและจากนั้น OFFSET และ LIMIT ในชุดนั้น ฉันได้อ่านแล้วว่านี่อาจเป็นเพราะ DBMS เลือกแผนแบบสอบถามแบบอื่นโดยพิจารณาจาก OFFSET และ LIMIT ตามลำดับโดยพลการ
บาร์ตัน

4
คำถามกำลังถามวงเงิน & สั่งซื้อโดย แต่คำตอบนั้นไม่เกี่ยวข้องกับคำถามนี้เลย
Shen liang

9

เช่นเดียวกับ @James พูดว่ามันจะสั่งระเบียนทั้งหมดแล้วรับ 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 มันยังสามารถยกเลิกแบบสอบถาม)
Martin Kersten

7

หากมีดัชนีที่เหมาะสมในกรณีนี้บนpublish_dateสนามแล้ว MySQL ไม่จำเป็นต้องสแกนดัชนีทั้งหมดเพื่อรับ 20 ระเบียนที่ร้องขอ - 20 ระเบียนจะพบที่จุดเริ่มต้นของดัชนี แต่ถ้าไม่มีดัชนีที่เหมาะสมการสแกนแบบเต็มตารางจะต้องใช้

มีบทความ MySQL Performance Blogตั้งแต่ปี 2009 เกี่ยวกับเรื่องนี้


7

คุณสามารถเพิ่ม [asc] หรือ [desc] ในตอนท้ายของการสั่งซื้อเพื่อรับระเบียนที่เร็วที่สุดหรือล่าสุด

ตัวอย่างเช่นนี้จะให้ระเบียนล่าสุดก่อน

ORDER BY stamp DESC

ต่อท้ายLIMITประโยคหลังORDER BY


3
ยินดีต้อนรับสู่ stackoverflow ฉันคิดว่าคุณอาจเข้าใจผิดคำถาม ฉันเชื่อว่าพวกเขาถูกถามเกี่ยวกับคำสั่งของการดำเนินงานมากกว่า "วิธีการเรียงลำดับ" (แต่มันก็เป็นสิ่งที่สงสัยตั้งแต่คำถามได้รับคำตอบไปแล้ว)
Leigh

5

คุณสามารถใช้รหัสนี้ SELECT article FROM table1 ORDER BY publish_date LIMIT 0,10 โดยที่ 0 คือขีด จำกัด เริ่มต้นของการบันทึก & 10 จำนวนการบันทึก


8
ไม่มีที่ไม่จำเป็น เป็นชวเลขLIMIT 10 LIMIT 0,10
Lawrence Dol

2
ใช่ไม่จำเป็นสำหรับ LIMIT 0,10 แต่คุณสามารถต้องการวงเงินนี้ได้ 10,20
gaurangkathiriya

3

LIMIT มักจะใช้เป็นการดำเนินการครั้งสุดท้ายดังนั้นผลลัพธ์จะถูกจัดเรียงก่อนแล้วจึง จำกัด ที่ 20 ในความเป็นจริงการเรียงลำดับจะหยุดทันทีที่พบผลลัพธ์ที่เรียง 20 อันดับแรก


11
ประโยคที่สองของคุณขัดแย้งกับประโยคแรกของคุณ การเรียงลำดับไม่สามารถหยุดได้เมื่อพบผลลัพธ์ 20 รายการแรกเพราะตามที่คุณกล่าวว่าการเรียงลำดับจะเสร็จสิ้นก่อนที่ผลลัพธ์จะถูกส่งคืน MySQL สามารถรู้ได้ว่าผลลัพธ์ 20 อันดับแรกหลังจากการเรียงลำดับเสร็จสิ้นแล้ว
Tom

@Tom จริง ๆ แล้วสามารถทำได้หากสั่งซื้อโดยคอลัมน์ที่จัดทำดัชนี มีการอธิบายไว้ที่นี่: dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
yitwail

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.