全部产品
Search
文档中心

数据管理 DMS:配置路由算法

更新时间:Oct 17, 2024

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

背景信息

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

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

使用场景

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

配置说明

数据管理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;
    }