数据库分片(shard)是一种在数据库的某些表变得特别大的时候采用的一种技术。

通过按照一定的维度将表切分,可以使该表在常用的检索中保持较高的效率,而那些不常用的记录则保存在低访问表中。比如:销售记录按照时间来切分。(横向切分)

也可以根据地域进行拆分,使得每个地区访问自己的表从而进行负载均衡。(纵向切分)

也可以纵横切分,使表拆的更细致。

也可以分库,让不同的数据存放在不同的服务器上,从而进一步均衡负载。

当遇到这样的事情的时候,如果不是采用了MongoDB这种自动拆表的工具,一般来说,都要自己实现一下切表的策略。其实,Hibernate中已经提供了一个很好用的包:

Hiberante Shard,该包是Google贡献给Hibernate社区的。根据其资料显示,现在这个包还是有些限制的。

比如:不能够进行跨表的order by,不能实现跨表的distinct,不能采用基础数据类型(如int)作为ID的类型。

但是它可以支持跨表的唯一ID,跨表的查询,跨表的累计...

而且它似乎只要少量的代码和简单的配置就可以使用,看来它真的是一个很好的工具。值得一试。

很不幸,网上的例子太少了,只找到了一段例子代码:

Hibernate Shards 数据的水平、垂直切割系列

这段代码下载之后运行了,由于数据量太少,并且生成在同一个表中,无法证明Hibernate Shards的作用。

官方网站的资料似乎也是惜墨如金,没有解释的非常详细。

Shards如何配置,如何使用呢?

一个工程里,有的表要切分,有的不必,如何做?

Shard和ebean如何结合使用呢?

带着这些课题,我开始了对Hibernate Shard的调查和研究。

Hibernate是一种ORM的包,它要有来自mapping.xml的“原型”,来自Java的Entity才能够形成ORMapping,还有一个数据库的表,它们的关系是一对一。

而如果采用分片技术,那么应该是一个原型,一个Entity,对应数据库的若干个结构相同的表。

在Hibernate Shard中,通过一个叫做“策略”的东西来完成这样的过程。

它允许通过定义不同的策略,来将不同分类的数据存放在不同的表(乃至库)中,而这个要通过一组和hibernate.cfg.xml结构一样的配置文件来定义。就像下面这样:

 <?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/test</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.pool_size">10</property>
<property name="show_sql">true</property>
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hbm2ddl.auto">validate</property>
<property name="hibernate.connection.shard_id">0</property>
<property name="hibernate.shard.enable_cross_shard_relationship_checks">false</property> <mapping resource="ContactEntity.hbm.xml" />
</session-factory> </hibernate-configuration>

然后在生成SessionFactory的时候采用这样的代码:

 private static SessionFactory createSessionFactory() {
Configuration prototypeCfg = new Configuration()
.configure("shard0.hibernate.cfg.xml");
List<ShardConfiguration> shardCfgs = new ArrayList<ShardConfiguration>();
shardCfgs.add(buildShardConfig("shard0.hibernate.cfg.xml"));
shardCfgs.add(buildShardConfig("shard1.hibernate.cfg.xml"));
ShardStrategyFactory strategyFactory = buildShardStrategyFactory();
ShardedConfiguration shardedConfig = new ShardedConfiguration(
prototypeCfg, shardCfgs, strategyFactory);
return shardedConfig.buildShardedSessionFactory();
}

而策略则分为三种:

ShardAccessStrategy

ShardSelectionStrategy

ShardResolutionStrategy

我们需要上述三种策略才能够构建Hibernate的SessionFactory,就像下面这样。

 private static ShardStrategyFactory buildShardStrategyFactory() {
return new ShardStrategyFactory() {
public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
ShardSelectionStrategy ss = new MyShardSelectionStrategy(shardIds);
ShardResolutionStrategy rs = new MyShardResolutionStrategy(shardIds);
ShardAccessStrategy as = new SequentialShardAccessStrategy();
return new ShardStrategyImpl(ss, rs, as);
}
};
}

那么这三种策略都是什么,应该怎么配置呢?

这三种策略的文档说明和代码说明不怎么一致。(说实在的,这段文档真的没怎么看懂,幸运的是,它是OpenSource的)

ShardAccessStrategy   文档说,切片访问策略,它定义了Hibernate如何和多个Shard之间进行访问。

幸运的是,Hibernate已经为我们创建了两个定义好了的ShardAccessStrategy,它们是:

SequentialShardAccessStrategy  (顺序切片访问策略) 和  ParallelShardAccessStrategy(并行切片访问策略)

顺序切片访问策略 如其名称所言,它按照顺序切片,资料显示,它有可能在访问无序数据时性能偏低,若是这种情况,官方建议使用LoadBalancedSequentialShardAccessStrategy。

                并行切片访问策略 如其名称所言,它提供了并行访问的策略,所以它同时要求提供一个并行策略执行器。 —— 听起来挺难得,而且,介绍资料说——这超纲了。

先不管这么多吧,假设我们访问的数据是一种,按地区、按年份增长的数据,每个城市个月增长量都在10万~1百万,那么我们要在这里采用什么策略呢?

数据是按照时间排序的,所以,我们可以采用SequentialShardAccessStrategy,按月分片,并且按照地区分片。

ShardSelectionStrategy  文档说定义了如何创建一个新对象。

代码上的注释说:Determine the specific shard on which this object should reside

         也就是说,这个是定义哪个领域用来存放这条数据的。

ShardResolutionStrategy 文档说是表示如何将数据进行分流的。比如我们提到的按地区、按月分片。那么数据需要根据这些条件存放在不同的表中。而ShardResolutionStrategy就是帮助我们来完成这个动作的。

代码注释上说:Determine the shards on which an object might live

在ShardStrategyFactory的newShardStrategy方法中传入的参数List<ShardId> shardIds会帮助我们进行选择区域动作。ShardId会定位对应的Continent。

我跟踪了一下那段例子代码,这里的shardIds表示有多少个hibernate.cfg.xml文件中的不同的shard_id字段的值。而ShardSelectionStrategy在Insert的时候会执行,而ShardResolutionStrategy则会在Select的时候执行。(update/delete尚未尝试。)

我们可以在ShardSelectionStrategy中建立自己的策略,比如,按照时间,按照地区来区分数据。从而把数据存放在不同的中。

因为shardx.hibernate.cfg.xml指定了不同的数据库,所以,到这里可以实现分库了。

而对于那些不必分表的直接return 0即可。

第一版的测试代码在这里下载

---------------

下一步我将研究一下,如何分表和如何结合Ebean。

Hibernate与数据库分表的更多相关文章

  1. MySQL数据库分表的3种方法

    原文地址:MySQL数据库分表的3种方法作者:dreamboycx 一,先说一下为什么要分表 当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了.分表的目 ...

  2. zabbix 数据库分表操作

    近期zabbix数据库占用的io高,在页面查看图形很慢,而且数据表已经很大,将采用把数据库的数据目录移到新的磁盘,将几个大表进行分表操作 一.数据迁移: 1.数据同步到新的磁盘上,先停止mysql(不 ...

  3. 数据库分表之Mybatis+Mysql实践(含部分关键代码)

    2018年01月31日      随着我们系统用户数量的日增,业务数据处于一个爆发前,增长的数据量已经给我们的系统造成了很大的不确定.在上个周末用户量较多,并发较大的情况下,读写频繁的验证码表,数据量 ...

  4. 一致性Hash算法在数据库分表中的实践

    最近有一个项目,其中某个功能单表数据在可预估的未来达到了亿级,初步估算在90亿左右.与同事详细讨论后,决定采用一致性Hash算法来完成数据库的自动扩容和数据迁移.整个程序细节由我同事完成,我只是将其理 ...

  5. Oracle亿级数据查询处理(数据库分表、分区实战)

    大数据量的查询,不仅查询速度非常慢,而且还会导致数据库经常宕机(刚接到这个项目时候,数据库经常宕机o(╯□╰)o). 那么,如何处理上亿级的数据量呢?如何从数据库经常宕机到上亿数据秒查?仅以此篇文章作 ...

  6. Mycat(4):消息表mysql数据库分表实践

    本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/46882777 未经博主同意不得转载. 1,业务需求 比方一个社交软件,比方像腾讯 ...

  7. MySQL数据库分表分区(一)(转)

    面对当今大数据存储,设想当mysql中一个表的总记录超过1000W,会出现性能的大幅度下降吗? 答案是肯定的,一个表的总记录超过1000W,在操作系统层面检索也是效率非常低的   解决方案: 目前针对 ...

  8. 数据库分表和分库的原理及基于thinkPHP的实现方法

    为什么要分表,分库: 当我们的数据表数据量,訪问量非常大.或者是使用频繁的时候,一个数据表已经不能承受如此大的数据訪问和存储,所以,为了减轻数据库的负担,加快数据的存储,就须要将一张表分成多张,及将一 ...

  9. mysql 数据库分表小实例

    项目开发中,我们的数据库数据越来越大,随之而来的是单个表中数据太多.以至于查询书读变慢,而且由于表的锁机制导致应用操作也搜到严重影响,出现了数据库性能瓶颈. 当出现这种情况时,我们可以考虑分表,即将单 ...

随机推荐

  1. android开发之路01

    一.android系统被分为4个层次:1.最下层的是linux核心,包括多个驱动程序,提供了操作系统应该具备的核心功能:2.在linux核心之上,包括两个部分,一部分是Android Runtime( ...

  2. NekoHTML and Dom4j

    http://pro.ctlok.com/2010/07/java-read-html-dom4j-nekohtml.html package com.ctlok.pro; import java.i ...

  3. kali Linux 文本图形界面切换遇到的怪问题

    前段装了在Virtual Box上装一个Kali Linux玩,然后设为了开机进入文本界面,后来遇到无法上网的问题,网上找到解决方法,说是NAT地址转换和host-only双网卡顺序问题,按照网上的说 ...

  4. mysql计算连续天数,mysql连续登录天数,连续天数统计

    mysql计算连续天数,mysql连续登录天数,连续天数统计 >>>>>>>>>>>>>>>>>& ...

  5. C#中的事件-订阅与发布

    我们用一个简单的例子,来说明一下这种消息传递的机制. 有一家三口,妈妈负责做饭,爸爸和孩子负责吃...将这三个人,想象成三个类. 妈妈有一个方法,叫做“做饭”.有一个事件,叫做“开饭”.做完饭后,调用 ...

  6. select2的基本用法

    公司有个项目需要用到类似百度搜索功能的下拉框,自然想到使用select2. 先看下select2的效果图,如下: 下来简单介绍下这个控件的基本用法,主要简单介绍下远程加载数据: 1.首先引入需要的文件 ...

  7. iis7下.Net框架版本设置

    转载:http://blog.163.com/fan_yishan/blog/static/47692213201391651229542/ Win7下IIS网站的.Net框架版本设置 步骤/方法 1 ...

  8. .Net 组件技术概述

    1. 基本原理 组件是组件系统中功能的表现,没有组件就没有功能.特定接口是用于给组件管理程序来操纵.管理该组件,特定功能是组件需要完成的任务.在一个使用组件建立的产品中会随着功能数目的多少而会有多个组 ...

  9. 利用sys.dm_db_index_physical_stats查看索引碎片等数据(转)

    我们都知道,提高sql server的数据查询速度,最有效的方法,就是为表创建索引,而索引在对数据进行新增,删除,修改的时候,会产生索引碎片,索引碎片多了,就需要重新组织或重新生成索引,以达到索引的最 ...

  10. 【JAVA】抽象类

    一.什么是抽象类 用abstract修饰的类就是抽象类.抽象类中可以有用abstract修饰的抽象方法,也可以没有抽象方法. 二.为什么要设计抽象类 在某些情况下,某个父类只是知道其子类应该包含怎样的 ...