一陈肛、場景舉例
1盏档、推送中心,從表中查詢千萬數(shù)據然后推送微信公眾號小程序燥爷;
2蜈亩、訪問某小程序的積分商城查看商品,一直滑動翻頁前翎,不用跳轉到指定頁數(shù)稚配;
3、從數(shù)據庫查詢百萬客戶數(shù)據寫入到redis港华;
二道川、線上問題
深度分頁問題SQL,如下所示:
SELECT
c,id,c.no,c.name
FROM
t_customer c
WHERE
c.delete_flag =0
order by c.id limit #{offset}立宜,#{pageSize}
這種常規(guī)的分頁回導致冒萄,當翻頁很深,offset越來越大橙数,回表的記錄越來越多尊流,sql查詢性能會急劇下降,會出現(xiàn)大量的慢SOL(超過1s的)
三灯帮、解決方案
limit用于分頁查詢時越往后翻性能越差崖技,解決的原則:縮小掃描范圍逻住,如下所示
1、子查詢
利用聚簇索引減少回表迎献,從而提升查詢效率瞎访,類似以下的SQL:
SELECT
c.id,c.name",c.no
FROM
t_customer c
where
c.id >= (select id from tcustomer WHERE delete_flag = 0 ORDER BY id imit #{loffset),1) limit #ipageSize)
2、內連接(inner join)
把子查詢(利用聚簇索引)的結果當成一張臨時表吁恍,然后和原表進行關聯(lián)查詢扒秸,類似以下的SOL:
SELECT
c.id,c.'name",c.no
FROM
t_customer c,
(SELECT id FROM t_customer WHERE delete_flag = 0 ORDER BY id LIMIT #{offset}, #{pageSize}) as d
where
c.id = d.id;
3、使用游標分頁查詢
當我們查詢第二頁的時候冀瓦,把第一頁的查詢結果(返回最后一條記錄的Id)放到第二頁的查詢條件中鸦采,類似以下的SQL:
SELECT
c.id,c.no,c.name
FROM
t_customer c
WHERE
c.delete_flag =and id > #{lastId} order by c.id limit #{pageSize};
線上總結: 如果數(shù)據量上千萬甚至上億了,使用第三種方案最好咕幻;如果定時任務Job查詢渔伯,也是使用第三種方案最好;如果是百萬級別的c端查詢肄程,可以用第一種或者第二種方案锣吼。
4、利用redis的pipeline批量寫入數(shù)據到redis蓝厌,提供寫入redis效率
同時玄叠,為了防止短時間寫入命令太高,導致redis cpu飆高拓提,可以每寫入一批读恃,sleep 500ms;
單機可以這樣操作代态,但是集群的話寺惫,性能不一定高,因為多個key不再同一集群節(jié)點上蹦疑。
pipeline 操作見Redis(九):Pipeline(管道)VS Lua(腳本)