赞
踩
Mysql分区:【还是在一个表里】,分表则在多张表了
说白就是sql语句,1.可以建静态的分区,2.也可以建动态的,3.还可以后来补充分区【下面的注释部分其实是执行的,尽管是灰色】
分区的几种方式:【也可以自己定义】
1.Range(范围)–这种模式允许将数据划分不同范围。例如可以将一个表通过年份划分成若干个分区。
2.Hash(哈希)–这中模式允许通过对表的一个或多个列的Hash
Key
进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区。例如可以建立一个对表主键进行分区的表。
3.Key
(键值)-上面Hash模式的一种延伸,这里的Hash
Key
是MySQL系统产生的。
4.List(预定义列表)–这种模式允许系统通过预定义的列表的值来对数据进行分割。
5.Composite(复合模式) –以上模式的组合使用
按照RANGE分区的表是通过如下一种方式进行分区的,每个分区包含那些分区表达式的值位于一个给定的连续区间内的行
LIST分区中每个分区的定义和选择是基于某列的值从属于一个值列表集中的一个值,而RANGE分 区是从属于一个连续区间值的集合。
上面的这个创建list分区时,如果有主銉的话,分区时主键必须在其中,不然就会报错。
如果我不用主键,分区就创建成功了,一般情况下,一个张表肯定会有一个主键,这算是一个分区的局限性吧。
如果对数据进行测试,请参考range分区的测试来操作
HASH分区主要用来确保数据在预先确定数目的分区中平均分布,你所要做的只是基于将要被哈希的列值指定一个列值或表达式,以 及指定被分区的表将要被分割成的分区数量。
按照KEY进行分区类似于按照HASH分区,除了HASH分区使用的用 户定义的表达式,而KEY分区的 哈希函数是由MySQL 服务器提供。
新增分区
ALTER TABLE sale_data
ADD PARTITION (PARTITION p201010 VALUES LESS THAN (
201011
));
删除分区
--当删除了一个分区,也同时删除了该分区中所有的数据。
ALTER TABLE sale_data DROP PARTITION p201010;
分区的合并
下面的SQL,将p201001 - p201009 合并为3个分区p2010Q1 - p2010Q3
ALTER TABLE sale_data
REORGANIZE PARTITION p201001,p201002,p201003,
p201004,p201005,p201006,
p201007,p201008,p201009 INTO
(
PARTITION p2010Q1 VALUES LESS THAN (
201004
),
PARTITION p2010Q2 VALUES LESS THAN (
201007
),
PARTITION p2010Q3 VALUES LESS THAN (
201010
)
);
Mysql分库分表方案
http://wentao365.iteye.com/blog/1740874mysql中有一种机制是表锁定和行锁定,是为了保证数据的完整性。
表锁定表示你们都不能对这张表进行操作,必须等我对表操作完才行。
行锁定也一样,别的sql必须等我对这条数据操作完了,才能对这条数据进行操作。
那么如何判断某张表的数据是否容量已满呢?可以在程序段对于要新增数据的表,
在插入前先做统计表记录数量的操作,当<500万条数据,就直接插入,
当已经到达阀值,可以在程序段新创建数据库表(或者已经事先创建好),再执行插入操作。
如果把业务切割得足够独立,那把不同业务的数据放到不同的数据库服务器将是一个不错的方案,而且
万一其中一个业务崩溃了也不会影响其他业务的正常进行,
并且也起到了负载分流的作用,大大提升了数据库的吞吐能力。
经过垂直分区后的数据库架构图如下:
如何来确定某个用户所在的shard呢,可以
建一张用户和shard对应的数据表,
每次请求先从这张表找用户的shard id,再从对应shard中查询相关数据,如下图所示:
不太严格的讲,对于海量数据的数据库,
如果是因为表多而数据多,这时候适合使用垂直切分,即把关系紧密(比如同一模块)的表切分出来放在一个server上。
如果表并不多,但每张表的数据非常多,这时候适合水平切分,即把表的数据按某种规则(比如按ID散列)切分到多个数据库(server)上。
当然,现实中更多是这两种情况混杂在一起,这时候需要根据实际情况做出选择,也可能会综合使用垂直与水平切分,从而将原有数据库切分成类似矩阵一样可以无限扩充的数据库(server)阵列。下面分别详细地介绍一下垂直切分和水平切分.
垂直切分的最大特点就是规则简单,实施也更为方便,
尤其适合各业务之间的耦合度非常低,相互影响很小,业务逻辑非常清晰的系统。
在这种系统中,可以很容易做到将不同业务模块所使用的表分拆到不同的数据库中。
根据不同的表来进行拆分,对应用程序的影响也更小,拆分规则也会比较简单清晰。(这也就是所谓的”share nothing”)。
二、切分策略
如前面所提到的,切分是按先垂直切分再水平切分的步骤进行的。
垂直切分的结果正好为水平切分做好了铺垫。
直切分的思路就是分析表间的聚合关系,把关系紧密的表放在一起。多数情况下可能是同一个模块,或者是同一“聚集”。这里的“聚集”正是领域驱动设计里所说的聚集。在垂直切分出的表聚集内,找出“根元素”(这里的“根元素”就是领域驱动设计里的“聚合根”),按“根元素”进行水平切分,也就是从“根元素”开始,把所有和它直接与间接关联的数据放入一个shard里。这样出现跨shard关联的可能性就非常的小。应用程序就不必打断既有的表间关联。比如:对于社交网站,几乎所有数据最终都会关联到某个用户上,基于用户进行切分就是最好的选择。再比如论坛系统,用户和论坛两个模块应该在垂直切分时被分在了两个shard里,对于论坛模块来说,Forum显然是聚合根,因此按Forum进行水平切分,把Forum里所有的帖子和回帖都随Forum放在一个shard里是很自然的。
对于共享数据数据,如果是只读的字典表,每个shard里维护一份应该是一个不错的选择,这样不必打断关联关系。如果是一般数据间的跨节点的关联,就必须打断。
需要特别说明的是:当同时进行垂直和水平切分时,切分策略会发生一些微妙的变化。比如:在只考虑垂直切分的时候,被划分到一起的表之间可以保持任意的关联关系,因此你可以按“功能模块”划分表格,但是一旦引入水平切分之后,表间关联关系就会受到很大的制约,通常只能允许一个主表(以该表ID进行散列的表)和其多个次表之间保留关联关系,也就是说:当同时进行垂直和水平切分时,在垂直方向上的切分将不再以“功能模块”进行划分,而是需要更加细粒度的垂直切分,而这个粒度与领域驱动设计中的“聚合”概念不谋而合,甚至可以说是完全一致,每个shard的主表正是一个聚合中的聚合根!这样切分下来你会发现数据库分被切分地过于分散了(shard的数量会比较多,但是shard里的表却不多),为了避免管理过多的数据源,充分利用每一个数据库服务器的资源,可以考虑将业务上相近,并且具有相近数据增长速率(主表数据量在同一数量级上)的两个或多个shard放到同一个数据源里,每个shard依然是独立的,它们有各自的主表,并使用各自主表ID进行散列,不同的只是它们的散列取模(即节点数量)必需是一致的。(
本文着重介绍sharding的基本思想和理论上的切分策略,关于更加细致的实施策略和参考事例请参考我的另一篇博文:数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示
)1.事务问题:
解决事务问题目前有两种可行的方案:分布式事务和通过应用程序与数据库共同控制实现事务下面对两套方案进行一个简单的对比。
方案一:使用分布式事务
优点:交由数据库管理,简单有效
缺点:性能代价高,特别是shard越来越多时
方案二:由应用程序和数据库共同控制
原理:将一个跨多个数据库的分布式事务分拆成多个仅处
于单个数据库上面的小事务,并通过应用程序来总控
各个小事务。
优点:性能上有优势
缺点:需要应用程序在事务控制上做灵活设计。如果使用
了spring的事务管理,改动起来会面临一定的困难。
2.跨节点Join的问题
只要是进行切分,跨节点Join的问题是不可避免的。但是良好的设计和切分却可以减少此类情况的发生。解决这一问题的普遍做法是分两次查询实现。在第一次查询的结果集中找出关联数据的id,根据这些id发起第二次请求得到关联数据。
3.跨节点的count,order by,group by以及聚合函数问题
这些是一类问题,因为它们都需要基于全部数据集合进行计算。多数的代理都不会自动处理合并工作。解决方案:与解决跨节点join问题的类似,分别在各个节点上得到结果后在应用程序端进行合并。和join不同的是每个结点的查询可以并行执行,因此很多时候它的速度要比单一大表快很多。但如果结果集很大,对应用程序内存的消耗是一个问题。
参考资料:
《MySQL性能调优与架构设计》
比如日志文章(article)表有如下字段:
面对这样的一个表,我们怎样切分呢?怎样将这样的数据分布到不同的数据库中的表中去呢?我们可以这样做,将user_id为1~10000的所有的文章信息放入DB1中的article表中,将user_id为10001~20000的所有文章信息放入DB2中的 article表中,以此类推,一直到DBn。这样一来,文章数据就很自然的被分到了各个数据库中,达到了数据切分的目的。
接下来要解决的问题就是怎样找到具体的数据库呢?其实问题也是简单明显的,既然分库的时候我们用到了区分字段user_id,那么很自然,数据库路由的过程当然还是少不了user_id的。就是我们知道了这个blog的user_id,就利用这个user_id,利用分库时候的规则,反过来定位具体的数据库。比如user_id是234,利用刚才的规则,就应该定位到DB1,假如user_id是12343,利用该才的规则,就应该定位到DB2。以此类推,利用分库的规则,反向的路由到具体的DB,这个过程我们称之为“DB路由”。
平常我们会自觉的按照范式来设计我们的数据库,考虑到数据切分的DB设计,将违背这个通常的规矩和约束。为了切分,我们不得不在数据库的表中出现冗余字段,用作区分字段或者叫做分库的标记字段。比如上面的article的例子中的user_id这样的字段(当然,刚才的例子并没有很好的体现出user_id的冗余性,因为user_id这个字段即使就是不分库,也是要出现的,算是我们捡了便宜吧)。当然冗余字段的出现并不只是在分库的场景下才出现的,在很多大型应用中,冗余也是必须的,这个涉及到高效DB的设计,本文不再赘述。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。