sharding-sphere路由概念

  • 路由:将原SQL转换成在真实数据库真实表中可执行SQL的过程。例如:
    SELECT * FROM t_order WHERE order_id IN (1, 2);
  • 路由后成为
    SELECT * FROM t_order_0 WHERE order_id IN (1, 2);
    SELECT * FROM t_order_1 WHERE order_id IN (1, 2);
  • 分片路由
  • 标准路由
    • 单片路由:原SQL分片键的操作符是等号,映射后只有一条可执行SQL。例如:
      SELECT * FROM t_order WHERE order_id=2;
      路由后成为
      SELECT * FROM t_order_0 WHERE order_id=2;
    • 多片路由:原SQL分片键的操作符是IN,映射后有多条可执行SQL。例如:
      SELECT * FROM t_order WHERE order_id IN (1, 2);
      路由后成为
      SELECT * FROM t_order_0 WHERE order_id IN (1, 2);
      SELECT * FROM t_order_1 WHERE order_id IN (1, 2);
    • 范围路由:原SQL分片键的操作符是BETWEEN,映射后有多条可执行SQL。
      SELECT * FROM t_order WHERE order_id BETWEEN (1, 12);
      路由后成为
      SELECT * FROM t_order_0 WHERE order_id BETWEEN (1, 12);
      SELECT * FROM t_order_1 WHERE order_id BETWEEN (1, 12);
    • 带有绑定表的多片路由:绑定表指分片规则一致的主表和子表。例如:t_order表和t_order_item表,均按照order_id分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。
      SELECT * FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE order_id IN (1, 2);
      路由后成为
      SELECT * FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE order_id IN (1, 2);
      SELECT * FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE order_id IN (1, 2);
  • 直接路由
    • Hint路由
      它需要通过Hint(使用HintAPI直接指定路由至库表)方式分片,并且是只分库不分表的前提下,则可以避免SQL解析和之后的结果归并。直接路由还可以用于分片键不在SQL中的场景。
      例如,设置用于数据库分片的键为3hintManager.setDatabaseShardingValue(3)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      String sql = "SELECT * FROM t_order";
      try (HintManager hintManager = HintManager.getInstance();
      Connection conn = dataSource.getConnection();
      PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
      hintManager.setDatabaseShardingValue(3);
      try (ResultSet rs = preparedStatement.executeQuery()) {
      while (rs.next()) {
      //...
      }
      }
      }
      路由算法为’value%2‘。当一个逻辑库order_database对应2个真实库order_database_0,order_databse_1时,路由后sql将在order_databse_1上执行。
  • 笛卡尔路由
    是指在关联查询中,各个表的分片键不同,没有绑定表。导致转换后的可执行SQL时,真实表之间需要进行笛卡尔积组合生成大量SQL。例如:
    假设分片键order_id将数值10路由至第0片,将数值11路由至第1片,那么路由后的SQL应该为4条,它们呈现为笛卡尔积:
    SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    路由后成为
    SELECT i.* FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    SELECT i.* FROM t_order_0 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    SELECT i.* FROM t_order_1 o JOIN t_order_item_0 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
    SELECT i.* FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id WHERE o.order_id in (10, 11);
  • 广播路由
  • 全库路由
    用于处理对数据库的操作,包括用于库设置的SET类型的数据库管理命令,以及TCL这样的事务控制语句。在这种情况下,会根据逻辑库的名字遍历所有符合名字匹配的真实库,并在真实库中执行该命令。
    例如 set autocommit=0
    在order_database中执行,order_database有两个真实库。则实际会在order_database_0,order_database_1上都执行这个命令。
  • 全库表路由
    用于处理对数据库中与其逻辑表相关的所有真实表的操作,主要包括不带分片键的DQL和DML,以及DDL等
    例如 SELECT * FROM t_order WHERE good_prority IN (1, 10);
    则会遍历所有数据库中的所有表,逐一匹配逻辑表和真实表名,能够匹配得上则执行。
    路由后成为
    SELECT * FROM t_order_0 WHERE good_prority IN (1, 10);
    SELECT * FROM t_order_1 WHERE good_prority IN (1, 10);
    SELECT * FROM t_order_2 WHERE good_prority IN (1, 10);
    SELECT * FROM t_order_3 WHERE good_prority IN (1, 10);
  • 全实例路由
    用于DCL操作,授权语句针对的是数据库的实例。无论一个实例中包含多少个Schema,每个数据库的实例执行一次。
    例如:
    create user customer@10.98.17.138 identified by '123';
    这个命令将在所有的真实数据库实例中执行,以确保customer用户可以访问每一个实例。
  • 单播路由
    用于获取某一真实表信息的场景,它仅需要从任意库中的任意真实表中获取数据即可。
    例如:
    DESCRIBE t_order;
    t_order的两个真实表t_order_0,t_order_1的描述结构相同,所以这个命令在任意真实表上选择执行一次。
  • 阻断路由
    用于屏蔽SQL对数据库的操作。
    例如:USE order_db;
    这个命令不会在真实数据库中执行,因为ShardingSphere采用的是逻辑Schema的方式,无需将切换数据库Schema的命令发送至数据库中。