假設業務某個場景中,須要查詢屢次查詢數據,sql以下:前端
startNum = i * 500; select id,content from test_table order by update_date asc limit " + startNum + ",500";
limit n,m定義爲:從第n行開始選擇m條記錄java
查詢表的數據量大體有36w左右,該sql是一個很是典型的排序+分頁查詢:order by col limit n,offset m , MySQL 執行此類sql時須要先掃描到N行,而後再去取 M行。對於此類大數據量的排序操做,取前面少數幾行數據會很快,可是越靠後,sql的性能就會越差,由於N越大,MySQL 須要掃描不須要的數據而後在丟掉,這樣耗費大量的時間。
sql
針對limit 優化有不少種方式,
一、前端加緩存,減小落到庫的查詢操做
二、優化SQL【策略1】
三、使用書籤方式 ,記錄上次查詢最新/大的id值,向後追溯 M行記錄。【策略3】
四、使用Sphinx 搜索優化。【策略2】
對於第二種方式 咱們推薦使用"延遲關聯"的方法來優化排序操做,何謂"延遲關聯" :經過使用覆蓋索引查詢返回須要的主鍵,再根據主鍵關聯原表得到須要的數據。數據庫
startNum = i * 500; select a.id,a.content from test_table a, (select id,content from test_table order by update_date asc limit " + startNum + ",500")b where a.id=b.id;
從以上sql能夠看出,咱們把limit n,m變成了一個條件,在外層加了一個聯表查詢。可能有朋友會問,這樣處理不也須要先查n筆,再日後面查m筆嗎?其實這樣說的也沒錯。只是,把n變成了一個條件這種處理方式叫作「延遲關聯」,它是先經過主鍵關聯查出來的,並非先去查n.m。這樣效率會高一點。具體效率是否提升,能夠explain一下這個sql,看下sql的執行計劃就清楚了。緩存
select id,content from test_table where xxx=n order by update_date asc limit m; 其中 xxx=n 爲一個有索引的字段;
索引不依賴於項目框架,能夠說跟框架沒有半毛錢關係,只要寫的是sql且能提交到數據庫去執行,條件走索引,就會走索引。走索引效率會提升。 框架
endNum = (i + 1)*500; select id,content from test_table where id > (select id,content from test_table order by id asc limit endNum,1) limit 500
這種方式與原sql對比,原sql須要跨越大量數據塊並取出,優化後基本經過直接根據索引字段定位,才取出相應內容,效率天然大大提高。性能