- 浏览: 313131 次
- 性别:
- 来自: 杭州
最新评论
-
wizard_hu:
<div class="quote_title ...
使用Eclipse Memory Analyzer进行内存泄漏分析三部曲 -
可爱的小狗:
学习了
HttpClient容易忽视的细节——连接关闭 -
xiajunhust:
<div class="quote_title ...
使用Eclipse Memory Analyzer进行内存泄漏分析三部曲 -
zhylandroid:
使用Eclipse Memory Analyzer进行内存泄漏分析三部曲 -
dsjt:
悲剧啊,google code 被墙了
mybatis3分表插件shardbatis 2.0
最近想在自己的项目里实现DB sharding功能,正好前段时间研究过ibatis的源码于是就在ibatis的基础上进行了一些修改。另一方面也是为了练练手。这个sharding的实现主要是基于我项目中的需求实现的可能有很多考虑不周的地方,希望各位大牛拍砖。如果有人感兴趣愿意一起来发展这个项目,本人也非常欢迎各位的加入。
Shardbatis是在mybatis 2.3.5代码的基础上进行一些扩展实现数据水平切分功能。 数据的水平切分包括多数据库的切分和多表的数据切分。目前shardbatis已经实现了单数据库的数据多表水平切分
mybatis2.3.5的核心类图(包含了spring对ibatis的封装SqlMapClientTemplate)如下(其他版本的ibatis的类图有略微不同)
改造后的类图
从这两张图上可以看出shardbatis里新增了接口SqlMapShardingExt,SqlMapShardingExt中具体的方法如下
通过SqlMapClientImpl和SqlMapSessionImpl对SqlMapShardingExt的实现是的ibatis具有了DB sharding的功能,iBATIS会自动根据配置的或者是编码的sharding策略将原始的sql语句转变为对应目标表名的sql。
下面看一下如何在iBATIS中配置和使用sharding功能
1.配置sharding策略。在sql-map-config.xml中添加如下配置
这里再通过实例简单介绍一下使用DefaultShardingStrategy时对sql的convert结果
比如sqlmap中定义的原始sql为:
那经过convert后的结果将可能是
又例如原始sql为
convert的结果可能为
开始使用sharding api
实现自己的sharding策略,只要实现一个简单的接口即可
Since 0.9.1使用ibatis原生api也可以支持sharding功能
下面开始编码
最终执行的SQL可能是如下样式
关于shardbatis在spring中的使用方法,以及一些使用注意事项和性能测试结果请大家移步到项目主页http://code.google.com/p/shardbatis/上查看
水平切分是会带来一些问题,但是既然我们已经做了水平切分,那么肯定是要牺牲一些东西的,比如数据库表的设计可能会反范式设计,简单的多表关联查询可能就没办法用了,诸如此类的问题,都会有。但是为了达到能容纳更多数据的目的,我觉得这样的牺牲是必要的。水平切分之后,我的理解就是其实RDBMS已经没有了关系,DB仅仅充当了Table的容器而已。如果还要使用关系的话,那么必然会给今后的扩展留下隐患。像时下流行的Key-Value系统,实现了什么?对外暴露出来的功能简单的就如同一个Map,但是确实是能解决一些问题的。是吧!
是的,我也是认为水平切分是有特定的应用场景的。如果要和其他表做关联或者做分页查询那是用水平切分就不是最好的解决方案了
水平切分是会带来一些问题,但是既然我们已经做了水平切分,那么肯定是要牺牲一些东西的,比如数据库表的设计可能会反范式设计,简单的多表关联查询可能就没办法用了,诸如此类的问题,都会有。但是为了达到能容纳更多数据的目的,我觉得这样的牺牲是必要的。水平切分之后,我的理解就是其实RDBMS已经没有了关系,DB仅仅充当了Table的容器而已。如果还要使用关系的话,那么必然会给今后的扩展留下隐患。像时下流行的Key-Value系统,实现了什么?对外暴露出来的功能简单的就如同一个Map,但是确实是能解决一些问题的。是吧!
如果你在一家小公司, 拥有数十亿的数据, 有比较大的访问要求, 买不起昂贵的存储, 买不起昂贵的小鸡。 你会怎么做? 搜索引擎。。。OPENSOURCE的, 有几个能处理大规模索引的?
那也要比select count(*) 数十亿数据来的快吧?如果分表,就不能多表联合查询了,要不分表还有什么意义。对于分页,应该通过分表的策略,让可能分页查询的数据都尽量在一个小表中。如果不能做到,或者单独计数,或者就不提供这种功能。
个人认为,分表分库不是用来做搜索的。更多用于服务器的负载均衡,我们也在iBatis基础上,结合spring实现了分库(保留分表的后期改造能力)。从性能上讲,分库(使用不同的物理服务器)视乎更好一些。
如果你在一家小公司, 拥有数十亿的数据, 有比较大的访问要求, 买不起昂贵的存储, 买不起昂贵的小鸡。 你会怎么做? 搜索引擎。。。OPENSOURCE的, 有几个能处理大规模索引的?
那也要比select count(*) 数十亿数据来的快吧?如果分表,就不能多表联合查询了,要不分表还有什么意义。对于分页,应该通过分表的策略,让可能分页查询的数据都尽量在一个小表中。如果不能做到,或者单独计数,或者就不提供这种功能。
如果你在一家小公司, 拥有数十亿的数据, 有比较大的访问要求, 买不起昂贵的存储, 买不起昂贵的小鸡。 你会怎么做? 搜索引擎。。。OPENSOURCE的, 有几个能处理大规模索引的?
大牛,果然就是大牛,一句话就给出了很好的解决方案。
让我开阔了思路。通过在sqlmap的xml里添加配置,程序的处理通过对jdbc的包装来处理。
非常感谢你的鼓励
关于你第一点的建议这个我不是没有考虑过,但是即使基于sqlmapclient现有的api也很难做到开发人员在开发时不去关心如何分表。打个比方说如果不做分表是直接存放在表(sub_table)中,调用sqlmapclient的insert方法是传递的参数可能直接用SubTable这个pojo。但是如果这个应用要根据数据产生的时间按月分表,这个时候仅靠pojo里的参数就不够了。因此我就新开了方法来做sharding的功能。不过我刚才考虑了一下可能很多时候靠sqlmapclient原有的api和外加一些配置是可以完成sharding功能的。这个可以做后新的特性在后面的版本中实现。谢谢你的建议。
至于你提到的第二点我理解的是不是你说的读写分库?关于数据库路由的功能准备在后面版本里加,在rodemap里我也写了,具体的实现方式欢迎您一起讨论,谢谢。
数据库水平切分是有特定的场景的,我做这个的目的不是为了解决水平切分的局限性。我做这个的目的是为了通过ibatis实现数据库水平切分的功能。
至于测试方法有不可靠的地方请您不吝赐教,谢谢!
也没有什么赐教的哈,分库分表的前提是在大数据量的前提下的。
呵呵,我这里的对比测试只是为了说明加上sharding功能以后对ibatis本身性能的影响,而不是测试大数据量下sql的性能,大数据量的性能说白了和shardbatis或者和ibatis都没有什么关系
数据库水平切分是有特定的场景的,我做这个的目的不是为了解决水平切分的局限性。我做这个的目的是为了通过ibatis实现数据库水平切分的功能。
至于测试方法有不可靠的地方请您不吝赐教,谢谢!
也没有什么赐教的哈,分库分表的前提是在大数据量的前提下的。
Shardbatis是在mybatis 2.3.5代码的基础上进行一些扩展实现数据水平切分功能。 数据的水平切分包括多数据库的切分和多表的数据切分。目前shardbatis已经实现了单数据库的数据多表水平切分
mybatis2.3.5的核心类图(包含了spring对ibatis的封装SqlMapClientTemplate)如下(其他版本的ibatis的类图有略微不同)
改造后的类图
从这两张图上可以看出shardbatis里新增了接口SqlMapShardingExt,SqlMapShardingExt中具体的方法如下
public interface SqlMapShardingExt extends SqlMapExecutor{ /** * 带有sharding功能的insert * @param id * @param parameterObject * @param groups * @return * @throws SQLException */ Object insertWithSharding(String id, Object parameterObject, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的insert * @param id * @param groups * @return * @throws SQLException */ Object insertWithSharding(String id, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的update * @param id * @param parameterObject * @param groups * @return * @throws SQLException */ int updateWithSharding(String id, Object parameterObject, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的update * @param id * @param groups * @return * @throws SQLException */ int updateWithSharding(String id, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的delete * @param id * @param parameterObject * @param groups * @return * @throws SQLException */ int deleteWithSharding(String id, Object parameterObject, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的delete * @param id * @param groups * @return * @throws SQLException */ int deleteWithSharding(String id, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的单记录查询 * @param id * @param parameterObject * @param groups * @return * @throws SQLException */ Object queryForObjectWithSharding(String id, Object parameterObject, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的单记录查询 * @param id * @param groups * @return * @throws SQLException */ Object queryForObjectWithSharding(String id, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的单记录查询 * @param id * @param parameterObject * @param resultObject * @param groups * @return * @throws SQLException */ Object queryForObjectWithSharding(String id, Object parameterObject, Object resultObject, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的查询 * @param id * @param parameterObject * @param groups * @return * @throws SQLException */ List queryForListWithSharding(String id, Object parameterObject, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的查询 * @param id * @param groups * @return * @throws SQLException */ List queryForListWithSharding(String id, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的查询 * @param id * @param parameterObject * @param skip * @param max * @param groups * @return * @throws SQLException */ List queryForListWithSharding(String id, Object parameterObject, int skip, int max, ShardingFactorGroup... groups) throws SQLException; /** * 带有sharding功能的查询 * @param id * @param skip * @param max * @param groups * @return * @throws SQLException */ List queryForListWithSharding(String id, int skip, int max, ShardingFactorGroup... groups) throws SQLException; /** * * @param id * @param parameterObject * @param rowHandler * @param groups * @throws SQLException */ void queryWithRowHandlerWithSharding(String id, Object parameterObject, RowHandler rowHandler, ShardingFactorGroup... groups) throws SQLException; /** * * @param id * @param rowHandler * @param groups * @throws SQLException */ void queryWithRowHandlerWithSharding(String id, RowHandler rowHandler, ShardingFactorGroup... groups) throws SQLException; /** * * @param id * @param parameterObject * @param keyProp * @param groups * @return * @throws SQLException */ Map queryForMapWithSharding(String id, Object parameterObject, String keyProp, ShardingFactorGroup... groups) throws SQLException; /** * * @param id * @param parameterObject * @param keyProp * @param valueProp * @param groups * @return * @throws SQLException */ Map queryForMapWithSharding(String id, Object parameterObject, String keyProp, String valueProp, ShardingFactorGroup... groups) throws SQLException;
通过SqlMapClientImpl和SqlMapSessionImpl对SqlMapShardingExt的实现是的ibatis具有了DB sharding的功能,iBATIS会自动根据配置的或者是编码的sharding策略将原始的sql语句转变为对应目标表名的sql。
下面看一下如何在iBATIS中配置和使用sharding功能
1.配置sharding策略。在sql-map-config.xml中添加如下配置
<shardingConfig> <!-- 对于app_test使用默认的切分策略,默认的切分策略只是简单按数值取模生成新的表名,如何实现切分策略后面再介绍 --> <sharding tableName="app_test" strategyClass="com.ibatis.sqlmap.engine.sharding.impl.DefaultShardingStrategy"/> <!-- 没有配置切分策略等于使用默认的切分策略 --> <sharding tableName="app_2test" /> </shardingConfig>
这里再通过实例简单介绍一下使用DefaultShardingStrategy时对sql的convert结果
比如sqlmap中定义的原始sql为:
SELECT EMPLOYEEIDNO FROM mytable WHERE SALARY >= 50000
那经过convert后的结果将可能是
SELECT EMPLOYEEIDNO FROM mytable_1 WHERE SALARY >= 50000
又例如原始sql为
SELECT a.* FROM ANTIQUES a,ANTIQUEOWNERS b, mytable c where a.id=b.id and b.id=c.id
convert的结果可能为
SELECT a.* FROM ANTIQUES_0 AS a, ANTIQUEOWNERS_1 AS b, mytable_1 AS c WHERE a.id = b.id AND b.id = c.id
开始使用sharding api
public class SqlMapClientTest { SqlMapClient sqlMapper; @Before public void init() { Reader reader; try { reader = Resources.getResourceAsReader("sql-map-config.xml"); sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader); reader.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Test public void testSharding() throws Exception { Map param = new HashMap(); param.put("cnt", "ttt"); ShardingFactorGroup g = new ShardingFactorGroup();//ShardingFactorGroup为切分策略提供必要参数 g.setTableName("App_Test");//设置为哪张表配置切分策略 g.setParam(new Integer(123));//设置为切分策略提供参数 //这里还可以通过g.setShardingStrategy(...)来设置切分策略 //通过API配置的切分策略可以覆盖xml里配置的App_Test表的切分策略 Integer count = (Integer) sqlMapper.queryForObjectWithSharding( "AppTest.select_paging_count_by_map", param, g); Assert.assertEquals(count.toString(), "0"); } @Test public void testUpdate() throws SQLException { ShardingFactorGroup g = new ShardingFactorGroup(); g.setTableName("App_Test"); g.setParam(new Integer(123)); String cnt = "testUpdate" + System.currentTimeMillis(); AppTest at1 = new AppTest(); at1.setCnt(cnt); Integer id = (Integer) sqlMapper.insertWithSharding( "AppTest.insert_h2", at1, g); AppTest parameterObject = new AppTest(); parameterObject.setCnt(cnt); AppTest ret = (AppTest) sqlMapper.queryForObjectWithSharding( "AppTest.select_by_condition", parameterObject, g); Assert.assertEquals(ret.getId().toString(), id.toString()); ret.setCnt("NEW_CONTENT"); Integer count = sqlMapper.updateWithSharding("AppTest.update", ret, g); Assert.assertEquals(count.toString(), "1"); count = (Integer) sqlMapper.queryForObjectWithSharding( "AppTest.select_paging_count", ret, g); Assert.assertEquals(count.toString(), "1"); } @Test public void testDelete() throws SQLException { ShardingFactorGroup g = new ShardingFactorGroup(); g.setTableName("App_Test"); g.setParam(new Integer(123)); String cnt = "testDelete" + System.currentTimeMillis(); AppTest at1 = new AppTest(); at1.setCnt(cnt); Integer id = (Integer) sqlMapper.insertWithSharding( "AppTest.insert_h2", at1, g); AppTest parameterObject = new AppTest(); parameterObject.setCnt(cnt); AppTest ret = (AppTest) sqlMapper.queryForObjectWithSharding( "AppTest.select_by_condition", parameterObject, g); Assert.assertEquals(ret.getId().toString(), id.toString()); Integer row = sqlMapper.deleteWithSharding("AppTest.delete", ret, g); Assert.assertEquals(row.toString(), "1"); } }
实现自己的sharding策略,只要实现一个简单的接口即可
public interface ShardingStrategy { /** * 计算得到新的表名 * @param baseTableName 逻辑表名 * @param params 为sharding逻辑提供必要参数 * @return */ public String getTargetTableName(String baseTableName,Object params); }
Since 0.9.1使用ibatis原生api也可以支持sharding功能
<!-- 在sql-map-config.xml中添加如下配置 --> <shardingConfig> <!-- 对于app_test使用默认的切分策略,默认的切分策略只是简单按数值取模生成新的表名,如何实现切分策略后面再介绍 --> <sharding tableName="app_test" strategyClass="com.ibatis.sqlmap.engine.sharding.impl.DefaultShardingStrategy"/> <!-- 没有配置切分策略等于使用默认的切分策略 --> <sharding tableName="app_2test" /> </shardingConfig> <!-- 在sqlmap.xml中statement节点都可以添加shardingParams属性 shardingParams对应的值使用json数组格式, paramExpr 对应parameterClass对象中的某个属性,这个属性的值会传递给sharding策略用于计算新的表名, 例如paramExpr:testId 等同于appTest.getTestId;paramExpr:model.id 等同于appTest.getModel().getId() tableName 用于表示当前这个json对象配使用于sql中的哪个表 strategyClass strateg接口实现类的全名,这个值如果没有将使用sql-map-config.xml里shardingConfig下配置对应的值。 --> <select id="select_count_native" parameterClass="AppTest" resultClass="java.lang.Integer" shardingParams='[{"paramExpr":"testId","tableName":"app_test"}]'> select count(*) from app_test where cnt=#cnt# </select>
下面开始编码
AppTest param=new AppTest(); param.setTestId(2); param.setCnt("testShardingWithConfig"); Integer count=(Integer)sqlMapper.queryForObject("AppTest.select_count_native",param);//和使用原生的ibatis API没有区别
最终执行的SQL可能是如下样式
select count(*) from app_test_0 where cnt=?
关于shardbatis在spring中的使用方法,以及一些使用注意事项和性能测试结果请大家移步到项目主页http://code.google.com/p/shardbatis/上查看
评论
25 楼
ah_asgx
2013-12-18
Hello 我想问一下:他好像不支持 top:
SELECT top 1 a.* FROM ANTIQUES a
会格式化成:
SELECT a.* FROM ANTIQUES a
SELECT top 1 a.* FROM ANTIQUES a
会格式化成:
SELECT a.* FROM ANTIQUES a
24 楼
ah_asgx
2013-12-18
Hello 我想问一下:他好像不支持 top:
SELECT top 1 a.* FROM ANTIQUES a
会格式化成:
SELECT a.* FROM ANTIQUES a
SELECT top 1 a.* FROM ANTIQUES a
会格式化成:
SELECT a.* FROM ANTIQUES a
23 楼
gubaojian
2013-04-22
楼主:这个组件还更新吗? 想贡献代码
22 楼
SeanHe
2010-09-29
lishuaibt 写道
J-catTeam 写道
数据库的水平切分 使用局限性还是有的。比如sql中的分组,排序,或者其他一些情况。
另外 兄弟 你的测试方法应该不是很可靠吧。
另外 兄弟 你的测试方法应该不是很可靠吧。
水平切分是会带来一些问题,但是既然我们已经做了水平切分,那么肯定是要牺牲一些东西的,比如数据库表的设计可能会反范式设计,简单的多表关联查询可能就没办法用了,诸如此类的问题,都会有。但是为了达到能容纳更多数据的目的,我觉得这样的牺牲是必要的。水平切分之后,我的理解就是其实RDBMS已经没有了关系,DB仅仅充当了Table的容器而已。如果还要使用关系的话,那么必然会给今后的扩展留下隐患。像时下流行的Key-Value系统,实现了什么?对外暴露出来的功能简单的就如同一个Map,但是确实是能解决一些问题的。是吧!
是的,我也是认为水平切分是有特定的应用场景的。如果要和其他表做关联或者做分页查询那是用水平切分就不是最好的解决方案了
21 楼
lishuaibt
2010-09-29
J-catTeam 写道
数据库的水平切分 使用局限性还是有的。比如sql中的分组,排序,或者其他一些情况。
另外 兄弟 你的测试方法应该不是很可靠吧。
另外 兄弟 你的测试方法应该不是很可靠吧。
水平切分是会带来一些问题,但是既然我们已经做了水平切分,那么肯定是要牺牲一些东西的,比如数据库表的设计可能会反范式设计,简单的多表关联查询可能就没办法用了,诸如此类的问题,都会有。但是为了达到能容纳更多数据的目的,我觉得这样的牺牲是必要的。水平切分之后,我的理解就是其实RDBMS已经没有了关系,DB仅仅充当了Table的容器而已。如果还要使用关系的话,那么必然会给今后的扩展留下隐患。像时下流行的Key-Value系统,实现了什么?对外暴露出来的功能简单的就如同一个Map,但是确实是能解决一些问题的。是吧!
20 楼
linliangyi2007
2010-09-28
这样架构的前提大多针对特定的互联网应用,如SNS系统,有较强的针对性,而不去考虑多表的join和分页这种问题
19 楼
linliangyi2007
2010-09-28
myreligion 写道
sdh5724 写道
SeanHe 写道
我个人认为如果对水平切分的数据要进行分页查询的话,可能会带来一些性能问题,可能最后没有了水平切分带来的优势。我觉的如果对水平切分的数据还要做分页查询的话,那还不如不要切分,可以选用其他的技术方案。比如说利用搜索引擎等
如果你在一家小公司, 拥有数十亿的数据, 有比较大的访问要求, 买不起昂贵的存储, 买不起昂贵的小鸡。 你会怎么做? 搜索引擎。。。OPENSOURCE的, 有几个能处理大规模索引的?
那也要比select count(*) 数十亿数据来的快吧?如果分表,就不能多表联合查询了,要不分表还有什么意义。对于分页,应该通过分表的策略,让可能分页查询的数据都尽量在一个小表中。如果不能做到,或者单独计数,或者就不提供这种功能。
个人认为,分表分库不是用来做搜索的。更多用于服务器的负载均衡,我们也在iBatis基础上,结合spring实现了分库(保留分表的后期改造能力)。从性能上讲,分库(使用不同的物理服务器)视乎更好一些。
18 楼
myreligion
2010-09-28
sdh5724 写道
SeanHe 写道
我个人认为如果对水平切分的数据要进行分页查询的话,可能会带来一些性能问题,可能最后没有了水平切分带来的优势。我觉的如果对水平切分的数据还要做分页查询的话,那还不如不要切分,可以选用其他的技术方案。比如说利用搜索引擎等
如果你在一家小公司, 拥有数十亿的数据, 有比较大的访问要求, 买不起昂贵的存储, 买不起昂贵的小鸡。 你会怎么做? 搜索引擎。。。OPENSOURCE的, 有几个能处理大规模索引的?
那也要比select count(*) 数十亿数据来的快吧?如果分表,就不能多表联合查询了,要不分表还有什么意义。对于分页,应该通过分表的策略,让可能分页查询的数据都尽量在一个小表中。如果不能做到,或者单独计数,或者就不提供这种功能。
17 楼
sdh5724
2010-09-28
SeanHe 写道
我个人认为如果对水平切分的数据要进行分页查询的话,可能会带来一些性能问题,可能最后没有了水平切分带来的优势。我觉的如果对水平切分的数据还要做分页查询的话,那还不如不要切分,可以选用其他的技术方案。比如说利用搜索引擎等
如果你在一家小公司, 拥有数十亿的数据, 有比较大的访问要求, 买不起昂贵的存储, 买不起昂贵的小鸡。 你会怎么做? 搜索引擎。。。OPENSOURCE的, 有几个能处理大规模索引的?
16 楼
SeanHe
2010-09-28
我个人认为如果对水平切分的数据要进行分页查询的话,可能会带来一些性能问题,可能最后没有了水平切分带来的优势。我觉的如果对水平切分的数据还要做分页查询的话,那还不如不要切分,可以选用其他的技术方案。比如说利用搜索引擎等
15 楼
Angi
2010-09-26
请问可以支持分页查询吗?
如果不支持,有这方面的计划吗?
谢谢!
如果不支持,有这方面的计划吗?
谢谢!
14 楼
SeanHe
2010-09-02
sdh5724 写道
哈哈, 直接在JDBC上做WRAPER的话, 会更干净~
大牛,果然就是大牛,一句话就给出了很好的解决方案。
让我开阔了思路。通过在sqlmap的xml里添加配置,程序的处理通过对jdbc的包装来处理。
13 楼
sdh5724
2010-09-02
哈哈, 直接在JDBC上做WRAPER的话, 会更干净~
12 楼
argan
2010-09-02
以前我也参考hibernate-sharding的思路做过一个封装 http://code.google.com/p/ibatis-sharding/
目标是尽量保持原来ibatis的使用习惯,功能和hibernate-sharding类似,很久没维护了,有兴趣的可以看看,代码也很简单
目标是尽量保持原来ibatis的使用习惯,功能和hibernate-sharding类似,很久没维护了,有兴趣的可以看看,代码也很简单
11 楼
yangguo
2010-09-01
比较牛。轮子上加个胎或绣朵花才是正途。
10 楼
SeanHe
2010-09-01
forthelichking 写道
比较支持这种增强行为,特别是在已经上线的项目里且用上了ibatis后,干净地增加了分表分库的能力,为以后的可维护性大大增强。
不过我觉得这种直接增加方法的方式有点繁琐了,dao最好是直接能用上ibatis原有的sqlMapClient提供的dao方法,这样一来,只用改动配置,不用改动代码,就能直接实现分库分表的逻辑,对于dao开发者来说,他根本无需关心数据库是否分库分表了,展现给他的操作逻辑就是一个库,一个表。
ps:最好是能把读写分离的逻辑也能干净地整合进去,之前的做法大部分人是用在spring事务里面配置readonly=true,不过互联网世界中压根就没有数据库事务的思想(严重影响性能),基本上用app的逻辑控制事务回滚之类的。
不过我觉得这种直接增加方法的方式有点繁琐了,dao最好是直接能用上ibatis原有的sqlMapClient提供的dao方法,这样一来,只用改动配置,不用改动代码,就能直接实现分库分表的逻辑,对于dao开发者来说,他根本无需关心数据库是否分库分表了,展现给他的操作逻辑就是一个库,一个表。
ps:最好是能把读写分离的逻辑也能干净地整合进去,之前的做法大部分人是用在spring事务里面配置readonly=true,不过互联网世界中压根就没有数据库事务的思想(严重影响性能),基本上用app的逻辑控制事务回滚之类的。
非常感谢你的鼓励
关于你第一点的建议这个我不是没有考虑过,但是即使基于sqlmapclient现有的api也很难做到开发人员在开发时不去关心如何分表。打个比方说如果不做分表是直接存放在表(sub_table)中,调用sqlmapclient的insert方法是传递的参数可能直接用SubTable这个pojo。但是如果这个应用要根据数据产生的时间按月分表,这个时候仅靠pojo里的参数就不够了。因此我就新开了方法来做sharding的功能。不过我刚才考虑了一下可能很多时候靠sqlmapclient原有的api和外加一些配置是可以完成sharding功能的。这个可以做后新的特性在后面的版本中实现。谢谢你的建议。
至于你提到的第二点我理解的是不是你说的读写分库?关于数据库路由的功能准备在后面版本里加,在rodemap里我也写了,具体的实现方式欢迎您一起讨论,谢谢。
9 楼
forthelichking
2010-09-01
比较支持这种增强行为,特别是在已经上线的项目里且用上了ibatis后,干净地增加了分表分库的能力,为以后的可维护性大大增强。
不过我觉得这种直接增加方法的方式有点繁琐了,dao最好是直接能用上ibatis原有的sqlMapClient提供的dao方法,这样一来,只用改动配置,不用改动代码,就能直接实现分库分表的逻辑,对于dao开发者来说,他根本无需关心数据库是否分库分表了,展现给他的操作逻辑就是一个库,一个表。
ps:最好是能把读写分离的逻辑也能干净地整合进去,之前的做法大部分人是用在spring事务里面配置readonly=true,不过互联网世界中压根就没有数据库事务的思想(严重影响性能),基本上用app的逻辑控制事务回滚之类的。
不过我觉得这种直接增加方法的方式有点繁琐了,dao最好是直接能用上ibatis原有的sqlMapClient提供的dao方法,这样一来,只用改动配置,不用改动代码,就能直接实现分库分表的逻辑,对于dao开发者来说,他根本无需关心数据库是否分库分表了,展现给他的操作逻辑就是一个库,一个表。
ps:最好是能把读写分离的逻辑也能干净地整合进去,之前的做法大部分人是用在spring事务里面配置readonly=true,不过互联网世界中压根就没有数据库事务的思想(严重影响性能),基本上用app的逻辑控制事务回滚之类的。
8 楼
lgdlgd
2010-09-01
我没有用过IBATIS,但最近研究了Hibernate shard这个项目,Hibernate shard没有解决分组、排序,分页用的是应用层面的内存分页,聊胜于无吧,不知道兄弟在这方面解决得如何
7 楼
SeanHe
2010-09-01
J-catTeam 写道
SeanHe 写道
J-catTeam 写道
数据库的水平切分 使用局限性还是有的。比如sql中的分组,排序,或者其他一些情况。
另外 兄弟 你的测试方法应该不是很可靠吧。
另外 兄弟 你的测试方法应该不是很可靠吧。
数据库水平切分是有特定的场景的,我做这个的目的不是为了解决水平切分的局限性。我做这个的目的是为了通过ibatis实现数据库水平切分的功能。
至于测试方法有不可靠的地方请您不吝赐教,谢谢!
也没有什么赐教的哈,分库分表的前提是在大数据量的前提下的。
呵呵,我这里的对比测试只是为了说明加上sharding功能以后对ibatis本身性能的影响,而不是测试大数据量下sql的性能,大数据量的性能说白了和shardbatis或者和ibatis都没有什么关系
6 楼
J-catTeam
2010-09-01
SeanHe 写道
J-catTeam 写道
数据库的水平切分 使用局限性还是有的。比如sql中的分组,排序,或者其他一些情况。
另外 兄弟 你的测试方法应该不是很可靠吧。
另外 兄弟 你的测试方法应该不是很可靠吧。
数据库水平切分是有特定的场景的,我做这个的目的不是为了解决水平切分的局限性。我做这个的目的是为了通过ibatis实现数据库水平切分的功能。
至于测试方法有不可靠的地方请您不吝赐教,谢谢!
也没有什么赐教的哈,分库分表的前提是在大数据量的前提下的。
发表评论
-
mybatis3分表插件shardbatis 2.0
2011-07-23 14:08 22118shardbait2.0实现分表的功能可以用一句话描述:使用m ... -
运行Apache Mahout的Taste Webapp例子
2011-07-14 20:00 10332Apache Mahout 是 Apache Soft ... -
编程式配置Spring bean
2011-02-15 23:29 2546今晚翻看了以前写的RPC框架。发现这个框架中编程式配置Spri ... -
JVM Crash原因分析及相关资料
2011-02-14 15:53 14927去年生产环境突然有一天连续发生几台服务器JVM Crash的情 ... -
一次jboss中部署应用时类版本冲突问题分析、解决过程
2011-02-10 10:11 9946去年同事的一个项目在JBOSS中部署时遇到类版本冲突问题,当时 ... -
java nio学习笔记
2011-01-30 00:37 0通道 和 缓冲区 是 NIO 中的核心对象,几乎在每一个 I/ ... -
使用Eclipse Memory Analyzer进行内存泄漏分析三部曲
2011-01-27 14:40 36568一、准备工作 分析较大的dump文件(根据我自己的经验2G以上 ... -
JBoss、Tomcat Classloader不完全分析
2010-12-14 13:25 3781由于平时项目中用到的还是JBoss 4.2.x所以我这里的分析 ... -
sitemesh性能测试结果比较惊艳(已经补上新的对比测试结果)
2010-07-17 17:03 6681最近想在一个项目中使用sitemesh作为view层的装饰器, ... -
Spring对Quartz的封装实现简单分析及使用注意事项
2010-06-14 14:08 9872前段时间在项目中一直使用正常的Quartz突然出现了任务漏跑的 ... -
Google App Engine for Java 开发笔记
2009-07-25 23:01 1816最近使用GAE开发一个小应用,开发过程中发现几个问题在这里做下 ... -
HttpClient容易忽视的细节——连接关闭
2008-08-30 12:22 130653HttpClient client = new HttpC ... -
为Hessian加入加密签名的安全机制
2008-03-09 10:01 5961Hessian是轻量级的RMI实现使用起来非常的方便,同时与S ... -
java DSA签名实现
2008-03-08 21:50 7190通过以下工具类可以生成DSA公钥和私钥文件 /** * ...
相关推荐
公司让学的 正在学习
基于struts+spring+ibatis的轻量级J2EE开发
基于半自动化iBatis的轻量级ORM改进研究
基于struts+spring+ibatis的轻量级J2EE开发.rar
ibatis api,ibatis文档,ibatis说明文档
iBatis 1、Spring嵌套iBatis框架 2、iBatis调用存储过程 3、iBatis中设置动态表查询 4、提高iBATIS性能的几个注意点
struts+spring+ibatis
IBATIS API 和IBATIS 的开发文档,很好的参考资料,要的赶快了
ibatis实现原理解析
个人感觉还行. 喜欢的可以学习下.较NHHIBERNATE简单得多. 见仁见智.欢迎拍砖.
ibatis实现分页技术,其中的分页都已经封装好了,大家需要的话可以下载下来看下
通过Ibatis实现简单的数据库的添加、删除、修改等功能的小小资料!
ibatis2.3 API CHM 帮助文档 ibatis 开发人员必备
ibatis2.0中文API ibatis2.0中文API ibatis2.0中文API 一对多 多对一详解,属性设置详解,解决方案详解,ibatis2.0核心API
ibatis api iBATIS-DAO-2_en.pdf 、iBATIS-SqlMaps-2-Tutorial_cn.pdf 、iBATIS-SqlMaps-2_cn.pdf 官网提供
Cobar Client是一个轻量级分布式数据访问层(DAL)基于iBatis(已更名为MyBatis)和Spring框架实现。主要特性:可以支持垂直和水平数据切分数据库集群的访问;支持双机热备的HA解决方案, 应用方可以根据情况选用数据库...
ibatis实现CRUD操作,它比学好hibernate更简单
ibatis学习 ibatis总结 ibatis ibatis ibatis
自己写的ibatis 框架,跟ibatis功能差不多