
SELECT * FROM demotable ORDER BY id LIMIT 2,4LIMIT後面接
[index, count]
:- Index:從哪個index開始傳回,Index是從0開始算,若以這個範例來看,資料會由第3筆資料開始回傳(2+1=3)
- count:由index開始,總共要傳回幾筆資料,以此範例來說,總共會傳回第3、4、5、6共四筆資料
SELECT * FROM demotable ORDER BY id LIMIT 4 OFFSET 2有些SQL的資料庫不支援[index,count]的格式(例如PostgreSQL),必需要用OFFSET來取代,OFFSET可以把它想成要略過筆數,以OFFSET 2為例,便可想成在找到的資料筆數中略過前二筆,即是由第三筆開始回傳。
但是隨著OFFSET (index) 的數量越大,其檢索性能便會越差。例如頭10萬或30萬筆數只需0.01秒,而去到50萬筆以上則需要3秒以上。為什麼會出現這樣的時間差異呢?其原因就在於表的掃描!假設我們要去執行LIMIT 5 OFFSEST 200000的資料讀取,MySQL便需要掃描出滿足條件的200005(200000+5)行的資料,然後再扔掉前面的200000行,返回最後的5行,OFFSET愈大當然會掃描得愈多。因此針對OFFSET問題我們需作出更多的優化考慮。
優化前SQL:
SELECT * FROM demoTable ORDER BY time LIMIT 200000,5
優化後SQL:
SELECT * FROM demoTable JOIN ( SELECT id FROM DemoTable ORDER BY times LIMIT 200000,5 ) USING (id)
另外,IN也是其中一個方法,但可惜我的MySQL還未更新。
SELECT * FROM demoTable WHERE id IN ( SELECT id FROM demoTable ORDER BY times LIMIT 200000,5 ); //ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery’
這個是不用OFFSET直接用WHERE來指向讀取index位置,但不適用於Time或Like Count的排序。
SELECT id FROM demoTable WHERE id > 200000 ORDER BY id desc LIMIT 6 OFFSET 0
分別在於,優化前的SQL需要浪費更多IO,而優化後的SQL則是預先讀取Primary key,後再以Primary key讀取數據,使其聽取速度加快。
首先是只讀取Primary key的部分。
除了INDEX會影響讀取的速度外,讀取的欄位也會一定程度的影響(有時遠比INDEX所帶來的影響更甚!),欄位讀取愈多愈會加重CPU以及內存的負擔,大大減低了整體IO效能。
SELECT * FROM demotable ORDER BY time DESC LIMIT 200000,5; //執行2秒 SELECT id FROM demotable ORDER BY time DESC LIMIT 200000,5; //執行0.5秒
而之後的部分便是以Primary Key來讀取真正需要的資料。
由於Subquery已幫我們篩選出了5筆資料的id,而且還是以primary key 當條件,讀取起來並不會費事。
整體而言,我們只需處理好subquery𥚃的index就可以了。
但需要注意的是MySQL會遞歸執行的subquery結果放在臨時表裡,因此太大的LIMIT也會影響效能。而且subquery本身也讓SQL的執行更加複雜化,太多的subquery反而不能達到預期效果。
0 留言:
發佈留言