ORDER BY 一般會有兩種實現方法,一個是利用有序索引自動實現,也就是說利用有序索引的有序性就再也不另作排序操做了。另外一個是把結果選好以後再排序。數據庫
用有序索引這種,固然是最快的,不過有一些限制條件,來看下面的測試。 性能
測試數據:student表有兩個字段id ,sid ,id是主鍵。一共有20W條記錄,id從1到200000,sid也是從1到200000的數據。 測試
第一種狀況 : 排序
order by的字段不在where條件也不在select中 索引
select sid from zhuyuehua.student where sid < 50000 order by id;內存
第二種狀況 :資源
order by的字段不在where條件但在select中。 io
select id,sid from zhuyuehua.student where sid < 50000 order by id;select
第三種狀況 : nio
order by的字段在where條件但不在select中。
select sid from zhuyuehua.student where sid < 50000 and id < 50000 order by id;
第四種狀況 :
order by的字段在where條件但不在select中。倒序排列
select sid from zhuyuehua.student where sid < 50000 and id < 50000 order by id desc;
測試結果:
order by的字段不在where條件不在select中 有排序操做
order by的字段不在where條件但在select中 有排序操做
order by的字段在where條件但不在select中 無排序操做
order by的字段在where條件但不在select中(倒序) 無排序操做
結論:
當order by 字段出如今where條件中時,纔會利用索引而無需排序操做。其餘狀況,order by不會出現排序操做。
分析:
爲何只有order by 字段出如今where條件中時,纔會利用該字段的索引而避免排序。這要說到數據庫如何取到咱們須要的數據了。
一條SQL實際上能夠分爲三步。
1.獲得數據
2.處理數據
3.返回處理後的數據
好比上面的這條語句select sid from zhuyuehua.student where sid < 50000 and id < 50000 order by id desc
第一步:根據where條件和統計信息生成執行計劃,獲得數據。
第二步:將獲得的數據排序。
當執行處理數據(order by)時,數據庫會先查看第一步的執行計劃,看order by 的字段是否在執行計劃中利用了索引。若是是,則能夠利用索引順序而直接取得已經排好序的數據。若是不是,則排序操做。
第三步:返回排序後的數據。
另外:
上面的5萬的數據sort只用了25ms,也許你們以爲sort不怎麼佔用資源。但是,因爲上面的表的數據是有序的,因此排序花費的時間較少。若是 是個比較無序的表,sort時間就會增長不少了。另外排序操做通常都是在內存裏進行的,對於數據庫來講是一種CPU的消耗,因爲如今CPU的性能加強,對 於普通的幾十條或上百條記錄排序對系統的影響也不會很大。可是當你的記錄集增長到上百萬條以上時,你須要注意是否必定要這麼作了,大記錄集排序不只增長了 CPU開銷,並且可能會因爲內存不足發生硬盤排序的現象,當發生硬盤排序時性能會急劇降低。
注:ORACLE或者DB2都有一個空間來供SORT操做使用(上面所說的內存排序),如ORACLE中是用戶全局區(UGA),裏面有SORT_AREA_SIZE等參數的設置。若是當排序的數據量大時,就會出現排序溢出(硬盤排序),這時的性能就會下降不少了。
總結:
當order by 中的字段出如今where條件中時,纔會利用索引而不排序,更準確的說,order by 中的字段在執行計劃中利用了索引時,不用排序操做。
這個結論不只對order by有效,對其餘須要排序的操做也有效。好比group by 、union 、distinct等。