添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
配置路由算法

配置路由算法

本文介绍路由算法配置的格式,及如何为逻辑表配置路由算法。

背景信息

路由算法是减少路由时开销的一种算法,逻辑表配置了路由算法后,带路由字段则可以快速查询指定物理表,免去人为计算、切换物理库表的操作。

路由算法的更多信息,请参见 路由算法

使用场景

  • 分表数据查询
  • 分表数据变更
  • 分表数据导出

配置说明

数据管理 DMS 分表路由算法采用 Groovy 表达式方式定义,与应用代码里使用配置的路由算法类似。

表达式格式: # +路由字段+ # 。例如 #shardKey#

配置路由算法

如下操作展示如何配置简单取模方式的路由算法。

  1. 在逻辑库下配置逻辑表。具体操作,请参见 逻辑表

  2. 逻辑表配置完成后,您可在全局搜索页面单击目标逻辑库右侧的 查询 ,进入 SQL 窗口页面。

    说明

    您也可以在顶部菜单栏中,选择 SQL 窗口 > SQL 窗口

  3. 在页面右上方单击 image.png ,进入表列表页面。

  4. 单击目标逻辑表行的 配置算法

  5. 在算法列表页面,单击 新增 ,配置 算法类型 取模方式 分表字段 模数

    本示例中的算法类型选择 单列取模 、取模方式选择 简单取模 ,分表字段选择 id,模数为 4,表达式为 #id#%4

    说明
    • 简单取模只能选中数字类型的字段进行取模。

    • 哈希取模可选择数字或者字符串类型的字段进行取模。

  6. 单击 保存

  7. 路由算法配置完成后,您可在逻辑表中查询表数据、执行 INSERT 语句。系统会根据计算的路由结果,将数据插入对应编号的分表中。

    例如插入一个 ID 9 的数据行,其计算的路由结果为 1,该数据将会插入 logic_table_01 分表中。

    image.png

路由表达式示例

如下表达式中的 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

    旧的 CorbarHash 算法

    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

    新的 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

    该算法可取字符串后四位,不足四位在左边补 0,最后四位每两位自动对换

    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

    该算法可获取指定最小长度的字符串,若长度不足则会在数字前补 0

    public static String lastSwapZero(String value, int length) {
      if (value.length() < length) {
          return StringUtils.leftPad(value, length, '0');
      return value;