參考文章:https://www.dexcoder.com/selfly/article/293
Mysql的分頁查詢十分簡單,但是當數據量大的時候一般的分頁就吃不消了。
傳統分頁查詢:SELECT c1,c2,cn… FROM table LIMIT n,m
MySQL的limit工作原理就是先讀取前面n條記錄,然后拋棄前n條,讀后面m條想要的,所以n越大,偏移量越大,性能就越差。
推薦分頁查詢方法:
1、盡量給出查詢的大致范圍
SELECT c1,c2,cn... FROM table WHERE id>=20000 LIMIT 10;
2、子查詢法
SELECT c1,c2,cn... FROM table WHERE id>= ( SELECT id FROM table LIMIT 20000,1 ) LIMIT 10;
3、高性能MySQL一書中提到的只讀索引方法
一般表中經常作為條件查詢的列都會建立索引,例如如下查詢
SELECT id, content FROM tb_chat ORDER BY create_time DESC LIMIT 24000, 20;
SELECT id, content FROM tb_chat INNER JOIN ( SELECT id FROM tb_chat ORDER BY create_time LIMIT 24000, 20 ) AS page USING(id);
這樣當前查詢頁的內容就只會在索引中進行,當得到當前頁的id再統一通過一個INNER JOIN得到最終要得到的數據詳情,避免了對大量數據詳情進行操作的消耗。當然JOIN操作也可以通過子查詢實現,不過書中介紹5.6之前版本的mysql相比子查詢還是優先使用JOIN。
對上一個sql繼續優化改進,當有查詢條件分頁時,一定要確保有數據是在limit后面的條件里,正常有輸入條件檢索查詢應該是limit 0, 10 我寫的是limit 15000,20只是為了測試,因為符合該條件的數據只有1萬5千多個,不然超出這個數就查不到數據了,切記。
SELECT id, content,c.z_type FROM tb_chat c INNER JOIN ( SELECT id,z_type FROM tb_chat WHERE z_type='1' ORDER BY create_time LIMIT 15000, 20 ) AS page USING(id);
等同於:
SELECT c.id, c.content,c.z_type FROM tb_chat c INNER JOIN ( SELECT id,z_type FROM tb_chat WHERE z_type='1' ORDER BY create_time LIMIT 15000, 20 ) AS p ON c.id=p.id;
個人覺得此方法更為通用,而且經過我的測試,發現表中總數據只有3萬條數據時兩個sql語句的執行時間竟然相差4倍,優化前的sql執行需要120ms,而優化后的sql需要30ms。
4、第一步用用程序讀取出ID,然后再用IN方法讀取所需記錄
程序讀ID:
SELECT id FROM table LIMIT 20000, 10; SELECT c1, c2, cn .. . FROM table WHERE id IN (id1, id2, idn.. .)