對于數據量很大的一張表,I/O效率低下,分表勢在必行!
數據庫數量漲到一定數量時,性能就成為我們不能不關注的問題。常用的方式基本有以下幾種:
1、分表,即把一個很大的表達數據分到幾個表中,這樣每個表數據都不多。
優點:提高并發量,減小鎖的粒度
缺點:代碼維護成本高,相關sql都需要改動
2、分區,所有的數據還在一個表中,但物理存儲數據根據一定的規則存放在不同的文件中,
文件也可以放到另外磁盤上
優點:代碼維護量小,基本不用改動,提高IO吞吐量
缺點:表的并發程度沒有增加
3、拆分業務,這個本質還是分表。
優點:長期支持更好
缺點:代碼邏輯重構,工作量很大
當然,每種情況都有合適的應用場景,需要根據具體業務具體選擇。由于分表和拆分業務和mysql本身關系不大屬于業務層面
1,使用程序分海量數據管理――文檔和圖像的壓縮和索引,對于不同的查詢,分配到不同的子表中,但是要修改代碼,查詢不透明。
分表的幾種方式
1、mysql集群
它并不是分表,但起到了和分表相同的作用。
集群可分擔數據庫的操作次數,將任務分擔到多臺數據庫上
。集群可以讀寫分離,減少讀寫壓力。從而提升數據庫性能。
2、自定義規則分表
大表可以按照業務的規則來分解為多個子表。通常為以下幾種類型,也可自己定義規則。
Range(范圍)–這種模式允許將數據劃分不同范圍。
例如可以將一個表通過年份劃分成若干個分區。

Hash(哈希)–這中模式允許通過對表的一個或多個列的Hash
Key進行計算,最后通過這個Hash碼不同數值對應的數據區域進行分區。
例如可以建立一個對表主鍵進行分區的表。
Key(鍵值)-上面Hash模式的一種延伸,這里的Hash Key是MySQL系統產生的。
List(預定義列表)–這種模式允許系統通過預定義的列表的值來對數據進行分割。
Composite(復合模式) –以上模式的組合使用
分表規則與分區規則一樣
根據日期查找表名,查詢的時候需要手動來判斷
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;
}
2, 分區(),在.1中實現,對存儲引擎沒有限制。
查看數據庫是否支持分區

show plugins; -- 在mysql控制臺中執行
據說5.4 以下的版本是
show variables like '%part%'; -- 待測試
Range 方式
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE
);
-- MAXVALUE 表示最大的可能的整數值
List方式
CREATE TABLE employees1 (
id INT NOT NULL,
fname VARCHAR (30),
lname VARCHAR (30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,

store_id INT
) PARTITION BY LIST (store_id)(
PARTITION pNorth
VALUES
IN (3, 5, 6, 9, 17),
PARTITION pEast
VALUES
IN (1, 2, 10, 11, 19, 20),
PARTITION pWest
VALUES
IN (4, 12, 13, 14, 18),
PARTITION pCentral
VALUES
IN (7, 8, 15, 16)
);
Hash 方式
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR (30),
lname VARCHAR (30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
) PARTITION BY HASH (store_id) PARTITIONS 4;
Key 方式
create table t_key(
a int(11),
b datetime)
partition by key (b)
partitions 4;
為每個分區指定指定具體的存儲磁盤,前提是磁盤必須是存在的
CREATE TABLE ts (id INT, purchased DATE)
ENGINE = MYISAM
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) ) (
PARTITION p0 VALUES LESS THAN (1990) (
SUBPARTITION s0
DATA DIRECTORY = '/disk0/data'
INDEX DIRECTORY = '/disk0/idx',
SUBPARTITION s1
DATA DIRECTORY = '/disk1/data'
INDEX DIRECTORY = '/disk1/idx'
),
PARTITION p1 VALUES LESS THAN (2000) (
SUBPARTITION s2
DATA DIRECTORY = '/disk2/data'
INDEX DIRECTORY = '/disk2/idx',
SUBPARTITION s3
DATA DIRECTORY = '/disk3/data'
INDEX DIRECTORY = '/disk3/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE (
SUBPARTITION s4
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s5
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
)
);
分區管理
新增分區
ALTER TABLE sale_data
ADD PARTITION (PARTITION p201010 VALUES LESS THAN (201011));
查詢分區
SELECT * FROM employees1 PARTITION (pNorth)
刪除分區(當一個分區刪除的時候,該分區中的數據也同時刪除)
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)
);
3, Merge存儲引擎,只支持 引擎。
MERGE表可以幫你解決以下問題:
容易地管理一套日志表。比如,你可以把不同月的數據放進分離的表中,用壓縮其中的一些,并隨后創建一個MERGE表來把它們當作一個來使用。
獲得更快的速度。你可以以一些標準來分割大的只讀表,然后放進不同磁盤上的單個表中。基于此的一個MERGE表可比使用大表要快得多。
執行更有效的搜索。如果你確切知道要搜索什么海量數據管理――文檔和圖像的壓縮和索引,對一些查詢你可以只在被分割的表的其中之一來搜索,并且對其它使用MERGE。你甚至有許多不同的MERGE表,它們使用有重疊的表套。
執行更有效的修補。修補被映射到一個MERGE表中的單個表比修補單個大型表要更輕松。
即刻映射許多表成一個。MERGE表不需要維護它自己的索引,因為它使用大哥表的所用。因此,MERGE表集合是非常塊地創建或重映射。(注意,當你創建一個MERGE表之時,即使沒有索引被創建,你必須仍然指定索引定義)。
如果根據需要或按照批次,你有一組要合起來作為一個大表的表,你應該根據需要對它們創建一個MERGE表來替代大表。這樣要快得多而且節約大量的磁盤空間。
超過操作系統的文件尺寸限制。每個表都受制于這個限制,但是一個表的集合則不然。
你可以通過定義一個映射到單個表的MERGE表來為一個表創建一個別名或“同物異名”。這樣做應該沒有真實的可察覺的性能影響 (對每個讀只有一些間接調用和()調用)。
MERGE表的缺點:
你可以對MERGE表使用僅相同的表。
你不能在MERGE表中使用很多功能。比如,你不能在MERGE表上創建索引。(當然,你可以在底層MERGE 表上創建索引,但是你不能用全文搜索來搜索MERGE表)。
如果MERGE表是非臨時的,所有底層表也必須是永久的。如果MERGE表是臨時的,表可以是任何臨時&非臨時的混合。
MERGE表使用更多的文件描述符。如果是個客戶端正使用一個映射到10個表的MERGE表,服務器使用(10*10)+10個文件描述符。(10個數據文件描述符給10個客戶端每人一個,并且在客戶端之間共享10個索引文件描述符)。
鍵讀會更慢。當你讀一個鍵的時候,MERGE存儲引擎需要在所 底層表上發出一個讀以檢查哪一個接近匹配給定的鍵。如果你隨后做了一個read-next,MERGE存儲引擎需要搜索讀緩沖來找出下一個鍵。只有當一個鍵緩沖被耗盡,存儲引擎才需要讀下一個 鍵塊。這使得MERGE鍵在搜索中非常慢,但在ref搜索中不是太慢。使用“ 語法(獲取相關信息)” 以獲得更多關于和ref的信息。