本文介紹路由算法配置的格式,及如何為邏輯表配置路由算法。
背景信息
路由算法是減少路由時開銷的一種算法,邏輯表配置了路由算法后,帶路由字段則可以快速查詢指定物理表,免去人為計算、切換物理庫表的操作。
路由算法的更多信息,請參見路由算法。
使用場景
- 分表數據查詢
- 分表數據變更
- 分表數據導出
配置說明
數據管理DMS分表路由算法采用Groovy表達式方式定義,與應用代碼里使用配置的路由算法類似。
表達式格式:#
+路由字段+#
。例如#shardKey#
。
配置路由算法
如下操作展示如何配置簡單取模方式的路由算法。
在邏輯庫下配置邏輯表。具體操作,請參見邏輯表。
邏輯表配置完成后,您可在全局搜索頁面單擊目標邏輯庫右側的查詢,進入SQL窗口頁面。
說明您也可以在頂部菜單欄中,選擇
。在頁面右上方單擊 ,進入表列表頁面。
單擊目標邏輯表行的配置算法。
在算法列表頁面,單擊新增,配置算法類型、取模方式、分表字段和模數。
本示例中的算法類型選擇單列取模、取模方式選擇簡單取模,分表字段選擇id,模數為4,表達式為
#id#%4
。說明簡單取模只能選中數字類型的字段進行取模。
哈希取模可選擇數字或者字符串類型的字段進行取模。
單擊保存。
路由算法配置完成后,您可在邏輯表中查詢表數據、執行INSERT語句。系統會根據計算的路由結果,將數據插入對應編號的分表中。
例如插入一個ID為9的數據行,其計算的路由結果為1,該數據將會插入logic_table_01分表中。
路由表達式示例
如下表達式中的user_id
為表字段示例值。
按表規則路由
簡單取模
數字取模:
#user_id#%100
二次取模:
#user_id#%10000%100
數字JavaHash取模:
Math.abs(#user_id#.hashCode())%100
字符串取模
數字字符串hash:
Math.abs(#user_id#.toString().hashCode())%100
字符串hash:
Math.abs(#user_id#.hashCode())%100
CobarHash:
Math.abs(cobarHash(#column#,start, end)).intdiv(8)
CobarOldHash:
Math.abs(cobarOldHash(#column#, len)).intdiv(8)
按庫規則路由
同名庫表規則:
'schema_prefix_'+(#user_id#%10)+'.table_name'
庫名和表名
'schema_prefix_'+(#user_id#%100)+'.table_name_prefix_'+(#user_id#%1000)
每個分庫內同一套分表:
'schema_prefix_'+lastSwapZero(String.valueOf((#user_id#%1024).intdiv(128),4)+'.table_name_prefix_'+lastSwapZero(String.valueOf((#user_id#%128)),4)
字符串的第16、17位數字除以2路由庫,字符串的第16、17位路由表:
'schema_prefix_'+substring(#EXTEND_ID#,16,18).toLong().intdiv(2)+'.table_name_prefix_'+substring(#EXTEND_ID#,16,18)
按日期路由
每月同一天路由到同一個表:
dayOfMonth(#time#)
按照字符串的倒數第三位進行路由
表名步長為10遞增乘以10,若為1則不需要乘:
Integer.valueOf(substring(#ip_id#,-3,-2))*10
其它復雜路由
自定義函數方式:
String func(String arg){ return arg.hashCode()%10;} 'table_name_'+func(#user_id#)+'_other_'func(#user_id#)
說明函數與表達式之間需要設置換行。
DMS支持
CRC32(java.util.zip.CRC32)
函數路由。
內置通用函數
cobarOldHash
public static long cobarOldHash(String s, int len) { long h = 0; int sLen = s.length(); for (int i = 0; (i < len && i < sLen); i++) { h = (h << 5) - h + s.charAt(i); } return h; }
cobarHash
public static long cobarHash(String s, int start, int end) { if (start < 0) { start = 0; } if (end > s.length()) { end = s.length(); } long h = 0; for (int i = start; i < end; ++i) { h = (h << 5) - h + s.charAt(i); } return h; }
weekOfYear
public static int weekOfYear(String dateValue) { Date date = DateTimeUtils.getSomeDate(dateValue); if(date != null) { return DateTimeUtils.getWeekOfYear(date); } return 0; }
dayOfYear
public static int dayOfYear(String dateValue) { Date date = DateTimeUtils.getSomeDate(dateValue); if(date != null) { return DateTimeUtils.getDayOfYear(date); } return 0; }
dayOfMonth
public static int dayOfMonth(String dateValue) { Date date = DateTimeUtils.getSomeDate(dateValue); if (date != null) { return DateTimeUtils.getDayOfMonth(date); } return 0; }
dayOfWeek
public static int dayOfWeek(String dateValue) { Date date = DateTimeUtils.getSomeDate(dateValue); if (date != null) { int dayOfWeek = DateTimeUtils.getDayOfWeek(date); if (dayOfWeek==1){ dayOfWeek=7; }else { dayOfWeek=dayOfWeek-1; } return dayOfWeek; } return 0; }
substring
public static String substring(String value, int start, int end) { return StringUtils.substring(value, start, end); }
public static String substring(String value, int start) { return StringUtils.substring(value, start); }
last4swap
public static String last4swap(String value) { if(value.length() < 4) { value = StringUtils.leftPad(value, 4, '0'); } return StringUtils.substring(value, -2)+StringUtils.substring(value, -4, -2); }
lastSwapZero
public static String lastSwapZero(String value, int length) { if (value.length() < length) { return StringUtils.leftPad(value, length, '0'); } return value; }