標籤:des style blog http color os 使用 io 檔案
用過mysql的人肯定知道,mysql提供了原生的分頁功能-----LIMIT關鍵字。LIMIT 子句可以被用於強制 SELECT 語句返回指定的記錄數。LIMIT 接受一個或兩個數字參數。參數必須是一個整數常量。如果給定兩個參數,第一個參數指定第一個返回記錄行的位移量,第二個參數指定返回記錄行的最大數目。TIPS:初始記錄行的位移量是 0(而不是 1)。
但是我再實際的項目過程中使用LIMIT子句時,在分頁數目很大的情況下(幾萬頁),後面的翻頁的速度明顯慢於前面,特別好奇這個現象的原因,於是explain了一下,才發現mysql LIMIT 10000, 20的意思掃描滿足條件的10020行,扔掉前面的10000行,返回最後的20行。如下所示:
EXPLAIN SELECT * FROM exp_platform ORDER BY id DESC LIMIT 10000,5
***************** 1. row **************
id: 1
select_type: SIMPLE
table: message
type: index
possible_keys: NULL
key: PRIMARY
key_len: 4
ref: NULL
rows: 10020
Extra:
1 row in set (0.00 sec)
這相當于越往後面翻頁越相當於全表掃描,這樣在一個高並發的應用下,效能肯定是hold不住的。但是LIMIT n這樣的語句效能是沒有問題的,因為只掃描n行。於是就想找解決辦法,如下:
Solution1:使用LIMIT n
"clue法":大概的思路就是在where語句根據id或者別的欄位做一些限制。但是這個思路只能提供“上一頁”、“下一頁”這樣的跳轉,因為你需要拿到上一頁或者下一頁的id然後再根據where語句篩選,再使用LIMIT N來做。這樣的話,不管翻多少頁,每次查詢只掃描20行。
SELECT * FROM exp_platform WHERE id >= 9500 LIMIT 5
Solution2:使用子查詢
SELECT * FROM exp_platform WHERE id >= (SELECT id FROM exp_platform ORDER BY id LIMIT 10000, 1) LIMIT 20
子查詢是在索引上完成的,而普通查詢是在資料檔案上完成的,通常來說,索引檔案要比資料檔案小很多,所以操作起來更有效
Solution3:使用JOIN分頁方式,這個沒有嘗試過,有機會可以試試。
實際可以利用類似策略模式的方式去處理分頁,比如判斷如果是一百頁以內,就使用最基本的分頁方式,大於一百頁,則使用子查詢的分頁方式。
mysql分頁的問題