Appearance
7 数据路由
分布式数据结构后端连接的是多个数据库资源,怎么将一条SQL正确发送到对应的节点执行这就是数据路由的作用。
7.1 表级路由
表级路由是指按照表的切分规则完成路由计算的方式。
7.1.1 直接路由
通过分片字段计算获取数据节点的方式称之为直接路由。
示例说明:
table1的schema.xml:配置如下
xml
<table name="table1" dataNode="dn1,dn2,dn3" rule="mod"></table>
rule.xml配置如下
xml
<tableRule name="mod">
<rule>
<columns>column1</columns>
<algorithm>mod</algorithm>
</rule>
</tableRule>
<!-- 路由函数定义 -->
<function name="mod" class="com.actiontech.dble.route.function.PartitionByLong">
<property name="partitionCount">3</property>
<property name="partitionLength">1</property>
</function>
执行SQL如下
sql
select * from table1 where column1 = value
table1表的是以column1字段根据mod算法完成的数据切分,SQL条件中包含分片字段id,在路由模块处理过程中可直接计算获取准确的数据节点。
7.1.2 间接路由
通过非分片字段间接获取数据节点的方式称之为间接路由。在处理方式上分为三种,下面分别阐述。
7.1.2.1 主键通过分片键间接路由
主键路由需要在table配置中包含primaryKey属性,在执行类似第一条SQL时会将结果集中的主键值与切分字段做映射并缓存起来,下次执行条件中包含主键的SQL时,就可以到准确的节点执行。但是如果查询字段中未包含主键则没有这层缓存处理。
配置示例:
xml
<table name="table1" dataNode="dn1,dn2,dn3" primaryKey="primary_key" rule="mod"></table>
如下SQL的where条件中只有primary_key,但其可以通过primary_key和分片键的关系实现间接路由:
sql
select * from table1 where primary_key = value
7.1.2.2 特殊字段通过分片键间接路由
特殊字段路由需要在table配置中包含indirectKeys属性,在执行第一条SQL时,内部处理会将查询记录中的间接路由字段column2与切分字段column1的值做映射并缓存,下次再执行条件中包含column2的SQL(类似第二条)时,就可以到准确的节点执行。如果查询字段中未包含间接路由的字段内部会拼接后做查询。
配置示例:
server.xml启动全局路由的开关:
xml
<property name="useIndirectRouteSwitch">true</property>
schema.xml的配置示例:
xml
<table name="table1" dataNode="dn1,dn2,dn3" indirectKeys="column2" rule="mod"></table>
如下SQL的where条件中的column2就可以通过和分片键的关系实现间接路由:
sql
select * from table1 where column2 = value
**说明:**这个功能的一个典型用法就是,当客户信息表按照客户号进行分片,但查询语句使用手机号或者身份证进行查询的场景。
7.1.2.3 子表通过主表的分片键间接路由
示例说明:
schema.xml配置如下:
sql
<table name="table1" dataNode="dn1,dn2,dn3" primaryKey="primary_Key" rule="mod">
<childTable name="table2" joinKey="join_key" parentKey="sharding_no"/>
</table>
rule.xml配置如下
xml
<tableRule name="mod">
<rule>
<columns>sharding_no</columns>
<algorithm>mod</algorithm>
</rule>
</tableRule>
<!-- 路由函数定义 -->
<function name="mod" class="com.actiontech.dble.route.function.PartitionByLong">
<property name="partitionCount">3</property>
<property name="partitionLength">1</property>
</function>
执行SQL如下
sql
select * from table2 where join_key = value
主子表需要按如上配置,parentKey为主表的分片字段,joinKey为子表的关联字段,这里的效果相当于子表继承了主表的切分规则,而子表table2的切分字段就是join_Key,所以在执行这条SQL时也可到准确的节点执行。但如果parentKey属性配置的不是主表的切分字段则在对子表操作时会先查出满足条件的主表记录在哪个节点,然后再确定的节点执行该SQL。
7.2 SQL级路由
SQL级路由是指用户可以通过特定方式指定SQL执行范围的路由方式。在LIBRA中是通过hint(注解)的形式来实现。下面是具体的方式。
7.2.1 指定到具体节点执行
hint中的一种类型是datanode,这里的datanode与schema.xml中的涵义相同,逻辑节点。
使用示例:
sql
/*!LIBRA:{'datanode':'dn1'}*/select * from table
这样注解后的SQL就只会到dn1节点执行。
7.2.2 指定跟某SQL一样的路由规则
hint中的一种类型是sql,注解外的SQL会在注解中的SQL路由的节点范围内去执行。
使用示例:
sql
/*!LIBRA:{'sql':'select * from table2 where sharding_no = value'}*/select * from table
7.2.3 指定跟某schema一样的路由规则
hint中的一种类型是schema,注解外的SQL会在注解中的SQL路由的节点范围内去执行。
使用示例:
sql
/*!LIBRA:{'schema':'TestDB'}*/select * from table
7.2.4 指定跟某数据库类型一样的路由规则
hint中的一种类型是db_type,注解外的SQL会在注解中的SQL路由的节点范围内去执行(db_type=master或者db_type=slave )。
使用示例:
sql
/*!LIBRA:{'db_type':'master'}*/select * from table
7.2.5 指定某归集库的路由规则
hint中的一种类型是归集库spe,注解外的SQL会在注解中的SQL路由的节点范围内去执行。
使用示例:
sql
/*!LIBRA:{'spe':''}*/select * from table