赞
踩
分片表,是指那些有很大数据,需要切分到多个数据库的表,这样每个分片都有一部分数据,所有分片构成了完整的数据。
table name=”t_goods” primaryKey=”vid” autoIncrement=”true” dataNode=”dn1,dn2” rule=”rulel” />
一个数据库中并不是所有的表都很大,某些表是可以不用进行切分的,非分片是相对分片表来说的,就是那些不需要进行数据切分的表。
<table name=”t_node” primaryKey=”vid” autolncrement=”true” dataNode=”dn1”/>
示例:
商家表,数量500万内
CREATE TABLE t_shops(
id BIGINT PRIMARY key AUTO_INCREMENT,
name VARCHAR(100) not NULL
);
<table name ="t_shops" primaryKey="id" dataNode="dn1"/>
INSERT INTO t_shops(name) values('stephanie001');
Mycat中的ER表是基于E-R关系的数据分片策略,子表的记录与所关联的父表记录存放在同一个数据分片上,保证数据Join不会跨库操作。
ER分片是解决跨分片数据join的一种很好的思路,也是数据切分规划的一条重要规则。
<table name=”customer” primaryKey=”ID” dataNode=”dn1,dn2” rule=”sharding-by-intfile”>
<childTable name=”orders” primaryKey=”ID” joinKey=”customer_id” parentKey=”id”>
<childTable name=”order_items”joinKey=”order_id” parentKey=”id” />
</childTable>
</table>
一个真实的业务系统中,往往存在大量的类似字典表的表,这些表基本上很少变动。
问题:业务表往往需要和字典表Join查询,当业务表因为规模而进行分片以后,业务表与字典表之间的关联跨库了。
解决:Mycat中通过表冗余来解决这类表的join,即它的定义中指定的dataNode上都有一份该表的拷贝。(将字典表或者符合字典表特性的表定义为全局表。)
适合数据量小的情况(10万条以下的数据)。
<table name=”company” primaryKey=”ID” type=”global” dataNode=”dn1,dn2,dn3” />
示例:
省份表t_province,在各个数据节点所在的库上分别创建全局表
CREATE TABLE t_province(
id INT PRIMARY KEY,
name VARCHAR(100) not NULL
);
用到了几个节点,节点上都要放上全局表,不然会出问题。
<table name ="t_province" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3"/>
重启mycat服务
插入数据
INSERT INTO t_province(id,name) values(1001,'浙江');
INSERT INTO t_province(id,name) values(1001,'江苏');
INSERT INTO t_province(id,name) values(1001,'上海');
INSERT INTO t_province(id,name) values(1001,'广东');
三个数据节点库上都同时写入了该数据。
在conf/rule.xml中定义分片规则
<?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE mycat:rule SYSTEM ”rule.dtd”> <mycat:rule xmlns:mycat=”http://io.mycat/”> <tableRule name=”rulel”> <rule> #只能是1列,如果是多列,再加个字段,把多个列的值合并在一起 <columns>id</columns> #分片算法 <algorithm>funcl</algorithm> </rule> </tableRule> <function name=”funcl” class=”io.mycat.route.function.PartitionByLong”> <property name=”partitionCount”>8</property> <property name=”partitionLength”>128</property> </function> </mycat:rule>
表分库虽然能解决大表对数据库系统的压力,但它并不是万能的,也有一些不利之处,因此首要问题是分不分库,分哪些库,什么规则分,分多少分片。
这里特别强调一下分片规则的选择问题,如果某个表的数据有明显的时间特征,比如订单、交易记录等,则他们通常比较合适用时间范围分片,因为具有时效性的数据,我们往往关注其近期的数据,查询条件中往往带有时间字段进行过滤,比较好的方案是,当前活跃的数据,采用跨度比较短的时间段进行分片,而历史性的数据,则采用比较长的跨度存储。
总体上来说,分片的选择
是取决于最频繁的查询SQL的条件
,因为不带任何Where语句的查询SQL,会便利所有的分片,性能相对最差,因此这种SQL越多,对系统的影响越大,所以我们要尽量避免这种SQL的产生。
如何准确统计和分析当前系统中最频繁的SQL呢?
有几个简单做法:
找出每个表最频繁的SQL,分析其查询条件,以及相互的关系,并结合ER图,就能比较准确的选择每个表的分片策略。
对于大家经常提起的同库内分表的问题,这里做一些分析和说明,同库内分表,仅仅是单纯的解决了单一表数据过大的问题,由于没有把表的数据分布到不同的机器上,因此对于减轻MySQL服务器的压力来说,并没有太大的作用,大家还是竞争同一个物理机上的IO、CPU、网络。
此外,库内分表的时候,要修改用户程序发出的SQL,可以想象一下A、B两个表各自分片5个分表情况下的JoinSQL会有多么的反人类。这种复杂的SQL对于DBA调优来说,也是个很大的问题。因此,Mycat和一些主流的数据库中间件
,都不支持库内分表
,但由于MySQL本身对此有解决方案,所以可以与Mycat的分库结合,做到最佳效果,下面是MySQL的分表方案:
通俗地讲MySQL分区是将一大表,根据条件分割成若干个小表。mysql5.1开始支持数据表分区了
。
如:某用户表的记录超过了600万条,那么就可以根据入库日期将表分区,也可以根据所在地将表分区。当然也可根据其他的条件分区。
MySQL分区支持的分区规则有以下几种:
在Mysql数据库中,Merge表有点类似于视图,mysql的merge引擎类型允许你把许多结构相同的表合并为一个表。之后,你可以执行查询,从多个表返回的结果就像从一个表返回的结果一样。每一个合并的表必须有完全相同表的定义和结构,但是只支持MyISAM引擎。
MysqlMerge表的优点:
在数据量、查询量较大的情况下,不要试图使用Merge表来达到类似于Oracle的表分区的功能,会很影响性能。和union几乎等价。
Mycat建议的方案是Mycat分库+MySQL分区,此方案具有以下优势:
mycat不建议在库内分表。一个库内还会造成数据库压力大的问题,并不能解决单点压力。
例如:单表数量达到800万才拆分
不到800万但跟大表(超800万的表)有关联查询的表也要拆分,在此称为大表关联表
大表关联表如何拆分:
如item_sku表250万,跟大表关联了,又无法跟大表使用相同拆分策略,也做成了全局表。
破例的全局表必须满足的条件:没有太激烈的并发update,如多线程同时update同一条id=1的记录。虽有多线程update,但不是操作同一行记录的不在此列。多线程update全局表的同一行记录会死锁。批量insert没问题。
拆分字段不能修改,否则容易造成数据不一致。
拆分字段只能是一个字段,如果想按照两个字段拆分,必须新建一个冗余字段,冗余字段的值使用两个字段的值拼接而成(如大区+年月拼成zone_yyyymm字段)。
按照选定的算法拆分后每个库中单表不得超过800万
如果某个表不跟其他表关联查询,数据量又少,直接不拆分,使用单库即可。
DataNode代表MySQL数据库上的一个Database,因此一个分片表的DataNode的分布可能有以下几种:
一般情况下,不建议第一种,二对于范围分片来说,在大多数情况下,最后一种情况最理想,因为当一个表的数据均匀分布在几个物理机上的时候,跨分片查询或者随机查询,都是到不同的机器上去执行,并行度最高,IO竞争也最小,因此性能最好。
当我们有几十个表都分片的情况下,怎样设计DataNode的分布问题,就成了一个难题,解决此难题的最好方式是试运行一段时间,统计观察每个DataNode上的SQL执行情况,看是否有严重不均匀的现象产生,然后根据统计结果,重新映射DataNode到DataHost的关系。
Mycat1.4增加了distribute函数,可以用于Table的dataNode属性上,表示将这些dataNode在该Table的分片规则里的引用顺序重新安排,使得他们能均匀分布到几个DataHost上:
<table name=”oc_ca11” primaryKey=”ID” dataNode=”distribute(dn1$0-372,dn2$0-372)” rule=”latest-monthcal1date”/>
其中dn1xxx与dn2xxxx是分别定义在DataHost1上与DataHost2上的377个分片
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。