【項目實戰】——歷史數據歸檔

遷移目標java

        按季度(每一個租戶自定義季度日期且各不相同)劃分,有明顯的冷熱數據區分,目標將冷數據分隔,減小單表過大,提供SQL等業務處理能力,期待預期按租戶自定義時間遷移,且遷移過程實現自動化,無需人工干預。sql

歸檔方案數據庫

        按各租戶自定義中季度日曆進行遷移,熱數據保留最近四個季度的數據,其餘數據,以日曆中設定的春暑秋寒四個季度爲年,進行年維度的歷史數據歸檔。服務器

執行方案數據結構

定時任務,每日執行定時任務,判斷各個租戶當前所屬季度,判斷上一年的該季度數據是否已經完成遷移,無遷移記錄,則進行數據遷移。mybatis

一、動態的建立歸檔數據表,此過程須要可複用,以知足多個數據表遷移歸檔的需求ide

二、分校存在一個季度有兩種日曆的狀況,須要數據所有遷移不可遺留工具

三、遷移的數據明細須要被記錄,以此保證冪等,避免數據被重複遷移.net

核心邏輯過程code

一、判斷目標表是否存在,不存在則建立

select count(*) from information_schema.TABLES where table_name = #{tableName}

返回數據爲0,則證實數據表不存在,建立目標表

利用mybatis中${},將表名稱和數據結構傳入,進行建立

<update id="createTable">
    create table ${tableName} ${content}
</update>

二、批量數據遷移提高效率

1).INSERT INTO SELECT語句

      語句形式爲:Insert into Table2(field1,field2,...) select value1,value2,... from Table1

      要求目標表Table2必須存在,因爲目標表Table2已經存在,因此咱們除了插入源表Table1的字段外,還能夠插入常量。

 2).SELECT INTO FROM語句

      語句形式爲:SELECT vale1, value2 into Table2 from Table1

      要求目標表Table2不存在,由於在插入時會自動建立表Table2,並將Table1中指定字段數據複製到Table2中

數據遷移以年爲單位,目標表Table2在遷移的時候必定是存在,故選用INSERT INTO SELECT方案,替代Insert INTO table(field1,field2,...) values(value1,value2,...)提高遷移效率,避免大量數據查詢再插入帶來應用服務器壓力

三、記錄已經遷移的數據(可複用)

CREATE TABLE `tb_move_data` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `biz_id` varchar(32) NOT NULL COMMENT '業務id',
  `city_code` varchar(8) NOT NULL COMMENT '租戶代碼',
  `table_name` varchar(32) NOT NULL COMMENT '表名',
  `num` int(11) NOT NULL COMMENT '遷移條數',
  `year` int(8) NOT NULL COMMENT '年',
  `term` int(8) NOT NULL COMMENT '季度',
  `start_time` datetime NOT NULL COMMENT '開始日期',
  `end_time` datetime NOT NULL COMMENT '截止日期',
  `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否刪除',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='數據遷移記錄';

利用insert into select 能夠獲取到遷移數據條數,將其餘業務信息拼接插入便可。

四、遷移完成後,移除原表中的已遷移數據,按期清理數據碎片。

歷史數據查詢處理

        利用ShardingJdbc的分片策略,由於以年爲單位且歷史歸檔表中並沒存有關於year相關內容,能夠經過Hint指定分片值而非從SQL中提取分片值的方式進行分片的策略。

public class PlanHintStrategy implements HintShardingAlgorithm<String> {
/**
*
* @param actualTables 物理表
* @param hintShardingValue 分片鍵,指定的表
* @return
*/
@Override
public Collection<String> doSharding(Collection actualTables, HintShardingValue hintShardingValue) {
List<String> shardingResult = new ArrayList<>();
actualTables.forEach(table -> {
String tableName = (String) table;
String suffix = tableName.substring(tableName.lastIndexOf("_") + 1);
Collection<String> tableNames = hintShardingValue.getValues();
if (tableNames.contains(suffix)) {
shardingResult.add(tableName);
}
});
return shardingResult;
}
}

在查詢以前先配置強制路由的分片便可

// Hint分片策略必需要使用 HintManager工具類
HintManager hintManager = HintManager.getInstance();
//查詢數據庫,能夠不配置
hintManager.addDatabaseShardingValue("tb_history_plan", 0);
//查詢分片表,能夠配置多個
hintManager.addTableShardingValue("tb_history_plan", "2019");
hintManager.addTableShardingValue("tb_history_plan", "2020")
// 直接指定對應具體的數據庫
hintManager.setDatabaseShardingValue(1);

關於hint策略推薦博客:https://blog.csdn.net/jobjava/article/details/106325053

相關文章
相關標籤/搜索