mysql分表和表分區詳解

爲何要分表和分區?html

平常開發中咱們常常會遇到大表的狀況,所謂的大表是指存儲了百萬級乃至千萬級條記錄的表。這樣的表過於龐大,致使數據庫在查詢和插入的時候耗時太長,性能低下,若是涉及聯合查詢的狀況,性能會更加糟糕。分表和表分區的目的就是減小數據庫的負擔,提升數據庫的效率,一般點來說就是提升表的增刪改查效率。java

什麼是分表?mysql

分表是將一個大表按照必定的規則分解成多張具備獨立存儲空間的實體表,咱們能夠稱爲子表,每一個表都對應三個文件,MYD數據文件,.MYI索引文件,.frm表結構文件。這些子表能夠分佈在同一塊磁盤上,也能夠在不一樣的機器上。app讀寫的時候根據事先定義好的規則獲得對應的子表名,而後去操做它。sql

什麼是分區?數據庫

分區和分表類似,都是按照規則分解表。不一樣在於分表將大表分解爲若干個獨立的實體表,而分區是將數據分段劃分在多個位置存放,能夠是同一塊磁盤也能夠在不一樣的機器。分區後,表面上仍是一張表,但數據散列到多個位置了。app讀寫的時候操做的仍是大表名字,db自動去組織分區的數據。併發

mysql分表和分區有什麼聯繫呢?
1.都能提升mysql的性高,在高併發狀態下都有一個良好的表現。
2.分表和分區不矛盾,能夠相互配合的,對於那些大訪問量,而且表數據比較多的表,咱們能夠採起分表和分區結合的方式(若是merge這種分表方式,不能和分區配合的話,能夠用其餘的分表試),訪問量不大,可是表數據不少的表,咱們能夠採起分區的方式等。
3.分表技術是比較麻煩的,須要手動去建立子表,app服務端讀寫時候須要計算子表名。採用merge好一些,但也要建立子表和配置子表間的union關係。
4.表分區相對於分表,操做方便,不須要建立子表。app

分表的幾種方式:less

一、mysql集羣高併發

它並非分表,但起到了和分表相同的做用。集羣可分擔數據庫的操做次數,將任務分擔到多臺數據庫上。集羣能夠讀寫分離,減小讀寫壓力。從而提高數據庫性能。性能

二、自定義規則分表

大表能夠按照業務的規則來分解爲多個子表。一般爲如下幾種類型,也可本身定義規則。

?
1
2
3
4
5
Range(範圍)–這種模式容許將數據劃分不一樣範圍。例如能夠將一個表經過年份劃分紅若干個分區。
Hash(哈希)–這中模式容許經過對錶的一個或多個列的Hash Key 進行計算,最後經過這個Hash碼不一樣數值對應的數據區域進行分區。例如能夠創建一個對錶主鍵進行分區的表。
Key (鍵值)-上面Hash模式的一種延伸,這裏的Hash Key 是MySQL系統產生的。
List(預約義列表)–這種模式容許系統經過預約義的列表的值來對數據進行分割。
Composite(複合模式) –以上模式的組合使用 

分表規則與分區規則同樣,在分區模塊詳細介紹。

下面以Range簡單介紹下如何分表(按照年份表)。

假設表結構有4個字段:自增id,姓名,存款金額,存款日期

把存款日期做爲規則分表,分別建立幾個表

2011年:account_2011

2012年:account_2012

……

2015年:account_2015

app在讀寫的時候根據日期來查找對應的表名,須要手動來斷定。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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存儲引擎來實現分表

merge分表,分爲主表和子表,主表相似於一個殼子,邏輯上封裝了子表,實際上數據都是存儲在子表中的。

咱們能夠經過主表插入和查詢數據,若是清楚分表規律,也能夠直接操做子表。

子表2011年

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
;

子表2012年

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
;

主表,全部年

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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:

?
1
2
3
4
5
6
7
8
9
10
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
);

List:

?
1
2
3
4
5
6
7
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)
 );

Hash:

?
1
2
3
4
5
create table hash(
  a int (11),
  b datetime
  )partition by hash ( YEAR (b)
  partitions 4;

Key:

?
1
2
3
4
5
create table t_key(
  a int (11),
  b datetime)
  partition by key (b)
  partitions 4;

分區管理

新增分區

?
1
2
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

?
1
2
3
4
5
6
7
8
9
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 )
);
相關文章
相關標籤/搜索