一、現狀
mysql下,某business單表已近2000萬且還在持續增加中,存在多個索引,有較高的查詢壓力。現業務端使用guava cache攔了一道,還能頂得住,但是后台管理系統的全量數據的分頁排序查詢比較慢,且將來會越來越慢。
二、目標
業務端+admin查詢都快。
三、解決方案
1.基於實際情況(大家一定要根據實際情況來),把數據庫拆為三個,如下:
- 熱數據(老表):提供CURD操作,事務加鎖等等,最大限度的不用更改原代碼。
- 半年內數據(history):只提供查詢業務。
- 半年之前數據(backup):歸檔,不提供業務查詢,只支持手動查庫(已跟產品溝通好)。
2.數據遷移,采用公司統一任務調度平台,注冊任務后調度執行,自帶WEB管理頁面。支持暫停、恢復、執行計划、日志查詢。
3.由於歷史數據過千萬,需要上線前進行一次手動遷移,初始化數據
1)history表保存:7天~半年,非進行狀態的數據。
2)backup表保存:半年前的,非進行狀態的數據。
3)刪除business表中,7天前的,非進行狀態的數據。
4. 后續每天凌晨定時任務遷移數據(遷移時注意:保證ID一致 )
business-->history >7天,非進行狀態的數據。
history-->backup >半年,非進行狀態的數據。
5.admin切到從庫讀。主從分離,避免從庫讀全量數據,導致業務端查詢緩慢。
四、采坑
1.千萬級帶索引刪除記錄,記得不能一次性直接delete,可以根據創建時間來,一次刪除百萬級數據,多分幾次刪除。否則容易出現假死,慢查詢,kill不掉執行sql.
2.注意初始化數據時候,可能當天多次執行,所以加上修改時間在當天前的,這樣多次執行,不會出現數據重復。
3.寫批量插入sql時,
1)不要用函數:sql中使用函數極端消耗時間。
2)不要用#,要用$:避免再次編譯消耗時間,這里不用怕什么sql注入,內部接口。
1 <insert id="transferTradingOrderByIds"> 2 insert into ${toTableName} (<include refid="Base_Column_List"/>) 3 select <include refid="Base_Column_List"/> 4 from ${fromTableName} 5 <where> 6 id in 7 <foreach collection="transferTradingOrderIds" item="id" separator="," open="(" close=")"> 8 ${id} 9 </foreach> 10 </where> 11 </insert>
五、結果
熱表數據:一百萬內,增刪改查極快。
歷史數據:一千萬內,查詢快。
歸檔數據:千萬級以上,慢,但是業務不調用。