MySQL中ORDER BY與LIMIT一塊兒使用(有坑)

1.  現象與問題html

ORDER BY排序後,用LIMIT取前幾條,發現返回的結果集的順序與預期的不同mysql

下面是我遇到的問題:sql

能夠看到,帶LIMIT與不帶LIMIT的結果與我預期的不同,並且「很難以想象」,真是百思不得其解服務器

後來百度了一下,若是order by的列有相同的值時,mysql會隨機選取這些行,爲了保證每次都返回的順序一致能夠額外增長一個排序字段(好比:id),用兩個字段來儘量減小重複的機率優化

因而,改爲 order by status, id;spa

問題雖然是解決了,但仍是看看官方文檔上怎麼說的吧!3d

2.  LIMIT查詢優化htm

——摘自「LIMIT查詢優化」blog

若是你只須要結果集中的指定數量的行,那麼請在查詢中使用LIMIT子句,而不是抓取整個結果集並丟棄剩下那些你不要的數據。排序

MySQL有時會優化一個包含LIMIT子句而且沒有HAVING子句的查詢:

  • MySQL一般更願意執行全表掃描,可是若是你用LIMIT只查詢幾行記錄的話,MySQL在某些狀況下可能會使用索引。
  • 若是你將LIMIT row_count子句與ORDER BY子句組合在一塊兒使用的話,MySQL會在找到排序結果的第一個row_count行後當即中止排序,而不是對整個結果進行排序。若是使用索引來完成排序,這將很是快。若是必須執行文件排序,則在找到第一個row_count行以前,選擇全部與查詢匹配但不包括LIMIT子句的行,並對其中大部分或全部行進行排序。一旦找到第一個row_count以後,MySQL不會對結果集的任何剩餘部分進行排序。這種行爲的一種表現形式是,一個ORDER BY查詢帶或者不帶LIMIT可能返回行的順序是不同的。
  • 若是LIMIT row_countDISTINCT一塊兒使用,一旦找到row_count唯一的行,MySQL就會中止。
  • LIMIT 0 能夠快速返回一個空的結果集,這是用來檢測一個查詢是否有效的一種頗有用的方法。
  • 若是服務器使用臨時表來解析查詢,它將使用LIMIT row_count子句來計算須要多少空間。
  • 若是ORDER BY不走索引,並且後面還帶了LIMIT的話,那麼優化器可能能夠避免用一個合併文件,並使用內存中的filesort操做對內存中的行進行排序。

若是ORDER BY列有多行具備相同的值,服務器能夠自由地以任何順序返回這些行,而且根據整體執行計劃可能以不一樣的方式返回。換句話說,這些行的排序順序對於無序列是不肯定的。

影響執行計劃的一個因素是LIMIT,所以對於一個ORDER BY查詢而言,帶與不帶LIMIT返回的行的順序多是不同的。

看下面的例子:

包含LIMIT可能會影響每個category行的順序。例如:

若是你須要確保不管帶不帶LIMIT都要以相同的順序返回,那麼你能夠在ORDER BY中包含附加列,以使順序具備肯定性。例如:

3.  小結

一、若是你只須要結果集中的某幾行,那麼建議使用limit。這樣這樣的話能夠避免抓取所有結果集,而後再丟棄那些你不要的行。

二、對於order by查詢,帶或者不帶limit可能返回行的順序是不同的。

三、若是limit row_countorder by 一塊兒使用,那麼在找到第一個row_count就中止排序,直接返回。

四、若是order by列有相同的值,那麼MySQL能夠自由地以任何順序返回這些行。換言之,只要order by列的值不重複,就能夠保證返回的順序。

五、能夠在order by子句中包含附加列,以使順序具備肯定性。

4.  文檔

https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html

https://dev.mysql.com/doc/refman/5.7/en/

https://dev.mysql.com/doc/

相關文章
相關標籤/搜索