什么是分表?
分表是将一个大表按照一定的规则分解成具有独立存储空间的实体表,可以称之为子表,每个表都对应3个文件,
MYD数据文件,.MYI索引文件,.frm表结构文件。这些子表可以分布在同一块磁盘上,也可以在不同的机器上。
读写的时候根据事先定义好的规则得到对应的子表名,然后去操作它。
什么是分区?
分区和分表相似,都是按照规则分解表。不同在于分表是将大表分解成若干个独立的实体表,而分区是将数据分段划分在
多个位置存放,可以是同一块磁盘也可以在不同的机器上。分区后,表面上还是一张表,但数据散列在不同的位置。读写的
时候操作的还是大表的名字,db会自动去组织分区的数据。
分表和分区的联系?
1:都能提高mysql的性能,在高并发的状态下都有一个良好的表现。
2:分表和分区并不矛盾,可以相互配合,对于那些大访问量,并且表数据比较多的表。我们可以采取分表和分区结合的方式
访问量不大,但是表数据很多的表,我们可以采取分区的方式。
3:分表技术是比较麻烦的,需要手动去创建子表,app服务端读写的时候需要计算子表名,采用merge好一些,但也要创建
子表和配置子表间的union关系。
4:表分区相对于分表,操作方便,不需要创建子表
自定义规则分表:
Range(范围)–这种模式允许将数据划分不同范围。例如可以将一个表通过年份划分成若干个分区。
Hash(哈希)–这中模式允许通过对表的一个或多个列的Hash
Key
进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区。例如可以建立一个对表主键进行分区的表。
Key
(键值)-上面Hash模式的一种延伸,这里的Hash
Key
是MySQL系统产生的。
List(预定义列表)–这种模式允许系统通过预定义的列表的值来对数据进行分割。
Composite(复合模式) –以上模式的组合使用
假设表结构有4个字段:自增id,姓名,存款金额,存款日期
把存款日期作为规则分表,分别创建几个表
2011年:account_2011
2012年:account_2012
……
2015年:account_2015
app在读写的时候根据日期来查找对应的表名,需要手动来判定
var getTableName =
function
() {
var data = {
name
:
'tom'
,
money: 2800.00,
date
:
'201410013059'
};
var tablename =
'account_'
;
var
year
= parseInt(data.
date
.
substring
(0, 4));
if (
year
< 2012) {
tablename += 2011; // account_2011
}
else
if (
year
< 2013) {
tablename += 2012; // account_2012
}
else
if (
year
< 2014) {
tablename += 2013; // account_2013
}
else
if (
year
< 2015) {
tablename += 2014; // account_2014
}
else
{
tablename += 2015; // account_2015
}
return
tablename;
}
merge分表,分为主表和子表,主表类似于一个壳子,逻辑上封装了子表,实际上数据都是存储在子表中的。
我们可以通过主表插入和查询数据,如果清楚分表规律,也可以直接操作子表
子表2011年:
CREATE
TABLE
`account_2011` (
`id`
int
(11)
NOT
NULL
AUTO_INCREMENT ,
`
name
`
varchar
(50)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
NULL
DEFAULT
NULL
,
`money`
float
NOT
NULL
,
`tradeDate` datetime
NOT
NULL
PRIMARY
KEY
(`id`)
)
ENGINE=MyISAM
DEFAULT
CHARACTER
SET
=utf8
COLLATE
=utf8_general_ci
AUTO_INCREMENT=2
CHECKSUM=0
ROW_FORMAT=
DYNAMIC
DELAY_KEY_WRITE=0
;
CREATE
TABLE
`account_2012` (
`id`
int
(11)
NOT
NULL
AUTO_INCREMENT ,
`
name
`
varchar
(50)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
NULL
DEFAULT
NULL
,
`money`
float
NOT
NULL
,
`tradeDate` datetime
NOT
NULL
PRIMARY
KEY
(`id`)
)
ENGINE=MyISAM
DEFAULT
CHARACTER
SET
=utf8
COLLATE
=utf8_general_ci
AUTO_INCREMENT=2
CHECKSUM=0
ROW_FORMAT=
DYNAMIC
DELAY_KEY_WRITE=0
;
CREATE
TABLE
`account_all` (
`id`
int
(11)
NOT
NULL
AUTO_INCREMENT ,
`
name
`
varchar
(50)
CHARACTER
SET
utf8
COLLATE
utf8_general_ci
NULL
DEFAULT
NULL
,
`money`
float
NOT
NULL
,
`tradeDate` datetime
NOT
NULL
PRIMARY
KEY
(`id`)
)
ENGINE=MRG_MYISAM
DEFAULT
CHARACTER
SET
=utf8
COLLATE
=utf8_general_ci
UNION
=(`account_2011`,`account_2012`)
INSERT_METHOD=
LAST
ROW_FORMAT=
DYNAMIC
;
创建主表的时候有个INSERT_METHOD,指明插入方式,取值可以是:0 不允许插入;FIRST 插入到UNION中的第一个表; LAST 插入到UNION中的最后一个表。
通过主表查询的时候,相当于将所有子表合在一起查询。这样并不能体现分表的优势,建议还是查询子表。
分区的几种方式:
Range:
create
table
range(
id
int
(11),
money
int
(11) unsigned
not
null
,
date
datetime
)partition
by
range(
year
(
date
))(
partition p2007
values
less than (2008),
partition p2008
values
less than (2009),
partition p2009
values
less than (2010)
partition p2010
values
less than maxvalue
);
create
table
list(
a
int
(11),
b
int
(11)
)(partition
by
list (b)
partition p0
values
in
(1,3,5,7,9),
partition p1
values
in
(2,4,6,8,0)
);
create
table
hash(
a
int
(11),
b datetime
)partition
by
hash (
YEAR
(b)
partitions 4;
create
table
t_key(
a
int
(11),
b datetime)
partition
by
key
(b)
partitions 4;
ALTER TABLE sale_data
ADD PARTITION (PARTITION p201010 VALUES LESS THAN (
201011
));
ALTER TABLE sale_data DROP PARTITION p201010;
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
)
);