mango框架中表分片与数据库分片(分表与分库)
表分片
表分片通常也被称为分表,散表。 当某张表的数据量很大时,sql执行效率都会变低,这时通常会把大表拆分成多个小表,以提高sql执行效率。 我们将这种大表拆分成多个小表的策略称之为表分片。
先来看一段mango框架中表分片的代码:
@DB(table = "t_order")
@Sharding(tableShardingStrategy = TableShardingOrderDao.OrderTableShardingStrategy.class)
public interface TableShardingOrderDao { @SQL("insert into #table(id, uid, price, status) values(:id, :uid, :price, :status)")
public void addOrder(@TableShardingBy("uid") Order order); @SQL("select id, uid, price, status from #table where uid = :1")
public List<Order> getOrdersByUid(@TableShardingBy int uid); class OrderTableShardingStrategy implements TableShardingStrategy<Integer> { @Override
public String getTargetTable(String table, Integer shardingParameter) {
return table + "_" + (shardingParameter % 2);
} } }
上面的代码实现了所有的表分片逻辑,以上面的代码为例,总结一下mango框架实现表分片的3个步骤:
- 填写@DB注解中的table参数,这个参数将启用 全局表名,上面代码的全局表名是t_order
- 引入 @Sharding 注解,并填写@Sharding注解中的tableShardingStrategy参数,这个参数的作用是定义表分片策略,上面代码使用了自定义的表分片策略OrderTableShardingStrategy
- 使用 @TableShardingBy 注解指定对表分片策略传入的参数。上面的代码中,调用 addOrder(@TableShardingBy("uid")Order order) 方法时,会使用order对象中的uid属性作为参数传递给第2步中的表分片策略,而调用 getOrdersByUid(@TableShardingBy int uid) 方法时,会使用uid作为参数传递给第2步中的表分片策略
上面的3个步骤步中,最核心的是第2步中的表分片策略。mango框架使用@Sharding注解中的tableShardingStrategy参数来指定表分片策略,tableShardingStrategy参数接受任何实现了 TableShardingStrategy 接口的类。
我们来看一下TableShardingStrategy接口的定义:
public interface TableShardingStrategy<T> { public String getTargetTable(String table, T shardingParameter); }
TableShardingStrategy接口非常简单,只有一个getTargetTable方法,其中:
- 输入参数table,对应的是全局表名
- 输入参数shardingParameter,接收被@TableShardingBy注解修饰的参数,shardingParameter的类型是泛型,将由实现类根据@TableShardingBy修饰的参数确定具体类型
- 输出则为真正的表名
以上面的OrderTableShardingStrategy表分片策略为例:
- 输入参数table将被传入字符串”t_order”
- 输入参数shardingParameter则会分两种情况,在调用 addOrder(@TableShardingBy("uid") Order order) 方法时,shardingParameter会被传入order对象中的uid属性,而在调用 getOrdersByUid(@TableShardingBy int uid) 方法时,shardingParameter会被传入参数uid
- 当uid为偶数时,使用t_order_0表,当uid为奇数时,使用t_order_1表
数据库分片
数据库分片通常也被称为分库,散库等。 当我们在某个库中,把某张大表拆分成多个小表后还不能满足性能要求,这时我们需要把一部分拆分的表挪到另外一个库中,以提高sql执行效率。
先来看一段mango框架中数据库分片的代码:
@DB()
@Sharding(databaseShardingStrategy = DatabaseShardingOrderDao.OrderDatabaseShardingStrategy.class)
public interface DatabaseShardingOrderDao { @SQL("insert into t_order(id, uid, price, status) values(:id, :uid, :price, :status)")
public void addOrder(@DatabaseShardingBy("uid") Order order); @SQL("select id, uid, price, status from t_order where uid = :1")
public List<Order> getOrdersByUid(@DatabaseShardingBy int uid); class OrderDatabaseShardingStrategy implements DatabaseShardingStrategy<Integer> { @Override
public String getDatabase(Integer shardingParameter) {
return shardingParameter < 1000 ? "db1" : "db2";
} } }
上面的代码实现了所有的数据库分片逻辑,以上面的代码为例,总结一下mango框架实现数据库分片的2个步骤:
- 引入 @Sharding 注解,并填写@Sharding注解中的databaseShardingStrategy参数,这个参数的作用是定义数据库分片策略,上面代码使用了自定义的数据库分片策略OrderDatabaseShardingStrategy
- 使用 @DatabaseShardingBy 注解指定对数据库分片策略传入的参数。上面的代码中,调用 addOrder(@DatabaseShardingBy("uid") Order order) 方法时,会使用order对象中的uid属性作为参数传递给第1步中的数据库分片策略,而调用 getOrdersByUid(@DatabaseShardingBy int uid) 方法时,会使用uid作为参数传递给第1步中的数据库分片策略
上面的2个步骤步中,最核心的是第1步中的数据库分片策略。mango框架使用@Sharding注解中的databaseShardingStrategy参数来指定数据库分片策略,databaseShardingStrategy参数接受任何实现了 DatabaseShardingStrategy 接口的类。
我们来看一下DatabaseShardingStrategy接口的定义:
public interface DatabaseShardingStrategy<T> { public String getDatabase(T shardingParameter); }
DatabaseShardingStrategy接口非常简单,只有一个getDatabase方法,其中:
- 输入参数shardingParameter,接收被@DatabaseShardingBy注解修饰的参数,shardingParameter的类型是泛型,将由实现类根据@DatabaseShardingBy修饰的参数确定具体类型
- 输出则为database名称
以上面的OrderDatabaseShardingStrategy数据库分片策略为例:
- 输入参数shardingParameter则会分两种情况,在调用 addOrder(@DatabaseShardingBy("uid") Order order) 方法时,shardingParameter会被传入order对象中的uid属性,而在调用 getOrdersByUid(@DatabaseShardingBy int uid)方法时,shardingParameter会被传入参数uid
- 当uid小于1000时,使用的database为db1,当uid大于等于1000时,使用的database为db2
同时使用数据库分片与表分片
我们将上面的数据库分片策略与表分片策略一起使用,形成同时使用数据库分片与表分片的代码:
@DB(table = "t_order")
@Sharding(
databaseShardingStrategy = ShardingOrderDao.OrderDatabaseShardingStrategy.class,
tableShardingStrategy = ShardingOrderDao.OrderTableShardingStrategy.class
)
public interface ShardingOrderDao { @SQL("insert into #table(id, uid, price, status) values(:id, :uid, :price, :status)")
public void addOrder(@DatabaseShardingBy("uid") @TableShardingBy("uid") Order order); @SQL("select id, uid, price, status from #table where uid = :1")
public List<Order> getOrdersByUid(@DatabaseShardingBy @TableShardingBy int uid); class OrderDatabaseShardingStrategy implements DatabaseShardingStrategy<Integer> { @Override
public String getDatabase(Integer uid) {
return uid < 1000 ? "db1" : "db2";
} } class OrderTableShardingStrategy implements TableShardingStrategy<Integer> { @Override
public String getTargetTable(String table, Integer uid) {
return table + "_" + (uid % 2);
} } }
上面的代码中,数据库分片策略使用了OrderDatabaseShardingStrategy,即uid小于1000时使用的database为db1,uid大于等于1000时使用的database为db2。 表分片策略则使用了OrderTableShardingStrategy,即uid为偶数时使用t_order_0表,uid为奇数时使用t_order_1表。
组合数据库分片策略与表分片策略得到如下规则:
- uid小于1000并且uid为偶数时,使用db1中的t_order_0表
- uid小于1000并且uid为奇数时,使用db1中的t_order_1表
- uid大于等于1000并且uid为偶数时,使用db2中的t_order_0表
- uid大于等于1000并且uid为奇数时,使用db2中的t_order_1表
精简分片代码
下面的代码同样实现了同时使用数据库分片与表分片,不过更加简洁。
@DB(table = "t_order")
@Sharding(shardingStrategy = ShardingOrder2Dao.OrderShardingStrategy.class)
public interface ShardingOrder2Dao { @SQL("insert into #table(id, uid, price, status) values(:id, :uid, :price, :status)")
public void addOrder(@ShardingBy("uid") Order order); @SQL("select id, uid, price, status from #table where uid = :1")
public List<Order> getOrdersByUid(@ShardingBy int uid); class OrderShardingStrategy implements ShardingStrategy<Integer, Integer> { @Override
public String getDatabase(Integer uid) {
return uid < 1000 ? "db1" : "db2";
} @Override
public String getTargetTable(String table, Integer uid) {
return table + "_" + (uid % 2);
} } }
上面的代码中,引入了@ShardingBy注解,@ShardingBy=@DatabaseShardingBy+@TableShardingBy。
多维度分片策略
上面的所有的代码我们都使用uid作为分片策略的计算参数,我们称之为一维分片策略。
考虑下面一个问题,当我们把数据库分片信息与表分片信息保存到order表中id字段的头部时,我们不但能把uid作为分片策略的计算参数,也能把id作为分片策略的计算参数。但@Sharding注解放在类上时,我们只能要么选择uid作为分片策略的计算参数,要们选择id作为分片策略的计算参数。这时我们需要将@Sharding注解下移到方法上,不同的方法指定不同的分片策略,实现多维度分片策略。
请看下面的代码:
@DB(table = "t_order")
public interface ShardingOrder3Dao { @SQL("insert into #table(id, uid, price, status) values(:id, :uid, :price, :status)")
@Sharding(shardingStrategy = ShardingOrder3Dao.OrderUidShardingStrategy.class)
public void addOrder(@ShardingBy("uid") Order order); @SQL("select id, uid, price, status from #table where uid = :1")
@Sharding(shardingStrategy = ShardingOrder3Dao.OrderUidShardingStrategy.class)
public List<Order> getOrdersByUid(@ShardingBy int uid); @SQL("select id, uid, price, status from #table where id = :1")
@Sharding(shardingStrategy = OrderIdShardingStrategy.class)
public Order getOrderById(@ShardingBy String id); class OrderUidShardingStrategy implements ShardingStrategy<Integer, Integer> { @Override
public String getDatabase(Integer uid) {
return uid < 1000 ? "db1" : "db2";
} @Override
public String getTargetTable(String table, Integer uid) {
return table + "_" + (uid % 2);
} } class OrderIdShardingStrategy implements ShardingStrategy<String, String> { @Override
public String getDatabase(String orderId) {
return "db" + orderId.substring(0, 1);
} @Override
public String getTargetTable(String table, String orderId) {
return table + "_" + orderId.substring(1, 2);
} } }
上面的代码中,addOrder(@ShardingBy("uid") Order order) 方法与 getOrdersByUid(@ShardingBy int uid) 方法使用了以uid作为参数的分片策略OrderUidShardingStrategy,而 getOrderById(@ShardingBy String id) 方法则使用了以id作为参数的分片策略OrderIdShardingStrategy。
查看完整示例代码和表结构
表分片与数据库分片 的所有代码和表结构均可以在 mango-example 中找到。
mango框架中表分片与数据库分片(分表与分库)的更多相关文章
- MySql从一窍不通到入门(五)Sharding:分表、分库、分片和分区
转载:用sharding技术来扩展你的数据库(一)sharding 介绍 转载:MySQL架构方案 - Scale Out & Scale Up. 转载: 数据表分区策略及实现(一) 转载:M ...
- MySql分表、分库、分片和分区的区别
一.前言 数据库的数据量达到一定程度之后,为避免带来系统性能上的瓶颈.需要进行数据的处理,采用的手段是分区.分片.分库.分表. 二.分片(类似分库) 分片是把数据库横向扩展(Scale Out)到多个 ...
- 支持MySql的数据库自动分表工具DBShardTools发布
支持MySql的数据库自动分表工具DBShardTools发布 前段时间参与了公司的一个项目,这个项目的特点是数据量.访问量都比较大,考虑使用数据库水平分表策略,Google了大半天,竟然没有找到分表 ...
- 数据库分表和分库的原理及基于thinkPHP的实现方法
为什么要分表,分库: 当我们的数据表数据量,訪问量非常大.或者是使用频繁的时候,一个数据表已经不能承受如此大的数据訪问和存储,所以,为了减轻数据库的负担,加快数据的存储,就须要将一张表分成多张,及将一 ...
- MySql分区、分表和分库
MySql分区.分表和分库 数据库的数据量达到一定程度之后,为避免带来系统性能上的瓶颈.需要进行数据的处理,采用的手段是分区.分片.分库.分表. 一些问题的解释: 1.为什么要分表和分区? 日常开发中 ...
- mysql数据库:分表、多表关联、外键约束、级联操作
一.分表.外键.级联.多对一 二.多对多 三.一对一 一.分表.外键.级联.多对一 将部门数据与员工数据放到同一张表中会造成 数据重复 结构混乱 扩展维护性差 需要分表 create table de ...
- Mysql分区、分表、分库
1.MySQL分区 一般情况下我们创建的表对应一组存储文件,使用MyISAM存储引擎时是一个.MYI和.MYD文件,使用Innodb存储引擎时是一个.ibd和.frm(表结构)文件. 当数据量较大时( ...
- 数据量大了一定要分表,分库分表组件Sharding-JDBC入门与项目实战
最近项目中不少表的数据量越来越大,并且导致了一些数据库的性能问题.因此想借助一些分库分表的中间件,实现自动化分库分表实现.调研下来,发现Sharding-JDBC目前成熟度最高并且应用最广的Java分 ...
- MySQL——分表,分库操作
说明 大数据量并且访问频繁的表,将其分为若干个表.如果不分的话,进行一次查询就会将表锁住,导致不能进行其他操作,故分表.表分割垂直分割应用场景:热数据放一个表里,冷数据放一个表里.冷数据使用MyIsa ...
随机推荐
- inux中fork()函数详解(原创!!实例讲解)
转载自原创博客,欢迎继续转载 点击跳转到原文
- html嵌入样式表
1.针对文件中的字体还有属性进行设置主要设置文字的大小及其颜色问题,未涉及div飘操作 处理页面CSS 先检测该内容部分是否已经设定了样式,如果没有单独设定再按照总体设计进行限定. eg: h1 h ...
- phpcms手机门户相关
相关标签 {$WAP['sitename']}标题 {list_url(3)} 调取栏目链接 {template "wap","header"}{templat ...
- ASM,C数据类型
汇编: db 单字节 = 8bit dw 单字 = 16bit dd 双字 = 32bit C数据类型: char 字节 8bit unsigned cha ...
- C#夯实基础系列之const与readonly
一.const与readonly的争议 你一定写过const,也一定用过readonly,但说起两者的区别,并说出何时用const,何时用readonly,你是否能清晰有条理地说出个一二三 ...
- Could not instantiate bean class [java.util.List]: Specified class is an interface] with root cause
最近项目中页面比较复杂,springMVC传参过程中遇到这样一个错误:Could not instantiate bean class [java.util.List]: Specified clas ...
- Ubuntu设置环境变量 16.04
打开终端并输入: sudo gedit /etc/environment. 2 输入用户密码.这时输入的密码是不可见的. 3 如图,在PATH="...."的末尾处添加: :/op ...
- 【转】Caffe初试(六)激活层及参数
在激活层中,对输入数据进行激活操作(实际上就是一种函数变换),是逐元素进行运算的.从bottom得到一个blob数据输入,运算后,从top输入一个blob数据.在运算过程中,没有改变数据的大小,即输入 ...
- mvc+webapi 单元测试
1.前言 现在这个项目已经有阶段性的模块完成了,所以就想着对这些模块进行单元测试,以保证项目的代码的质量.首先虽然标题是mvc+webapi实质上我只是对mvc进行的测试.用的时候vs的unit te ...
- eclipse远程连接hive
创建项目,添加jar包,hive的s上,所以也需要hadoop的一些jar 这个图片是从网上找的,我直接使用的以前hadoop的项目 创建测试类,写测试代码 //获取jdbc链接 private ...