某些行業數據量的增長速度極快,隨着數據庫中數據量的急速膨脹,數據庫的插入和查詢效率越來越低。此時,除了程序代碼和查詢語句外,還得在數據庫的結構上做點更改;在一個主讀輔寫的數據庫中,當數據表數據超過1000w行后,那查詢效率真的很讓人抓狂。就算早前建了索引,也很難滿足用戶對於系統查詢效率的體驗。
優化方案是分表或分區。至於分區的原理以及分區和分表的區別,搜索一下,都介紹的很詳細,這里就不作冗余介紹。簡單來講,分表旨在提高數據庫的並發能力,分區旨在優化磁盤的IO和數據的讀寫,所以采用什么方案,還得根據業務再作斟酌。由於我們的系統對並發要求不高,所以便采用了分區。
分區是MySQL5.1以后實現的。其中分區類型有RANGE分區、LIST分區、HASH分區、KEY分區。我們這里是使用RANGE分區來講解。
分區需要注意的一點是:要么不定義主鍵,要么把分區字段添加到主鍵中。並且分區字段不能為NULL,要不然就難以確定分區范圍。所以要設為NOT NULL。
首先執行一下show plugins; 查看partition這一欄是否為ACTIVE,是則表示數據庫支持分區。
1、創建一個數據表並分區:
CREATE TABLE ` table_name` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`uid` VARCHAR(50) DEFAULT NULL,
`action` VARCHAR(10) DEFAULT NULL,
` channel` VARCHAR(20) DEFAULT NULL,
`count_left` INT(11) DEFAULT NULL,
`end_time` INT(11) DEFAULT '0',
PRIMARY KEY (`id`,`end_time`),
KEY `time` (`end_time`)
) ENGINE=MYISAM DEFAULT CHARSET=utf8
PARTITION BY RANGE(`end_time`) (
PARTITION p161130 VALUES LESS THAN (1480550399),
PARTITION p161231 VALUES LESS THAN (1483228799),
PARTITION p170131 VALUES LESS THAN (1485907199),
PARTITION p170228 VALUES LESS THAN (1488326399),
PARTITION p170331 VALUES LESS THAN (1491004799),
PARTITION p170430 VALUES LESS THAN (1493596799),
PARTITION p170531 VALUES LESS THAN (1496275199),
PARTITION p170631 VALUES LESS THAN (1498867199),
PARTITION pnow VALUES LESS THAN MAXVALUE
);
2、修改一個數據表分區:
ALTER TABLE `table_name`
PARTITION BY RANGE(`end_time`) (
PARTITION p161130 VALUES LESS THAN (1480550399),
PARTITION p161231 VALUES LESS THAN (1483228799),
PARTITION p170131 VALUES LESS THAN (1485907199),
PARTITION p170228 VALUES LESS THAN (1488326399),
PARTITION p170331 VALUES LESS THAN (1491004799),
PARTITION p170430 VALUES LESS THAN (1493596799),
PARTITION p170531 VALUES LESS THAN (1496275199),
PARTITION p170631 VALUES LESS THAN (1498867199),
PARTITION pnow VALUES LESS THAN MAXVALUE
);
說明:1、2中使用end_time (時間是以時間戳的形式記錄的) 作為分區字段對表進行分區。分區的區分值為分區名中的時間的時間戳形式,比如2016/11/30 23:59:59 轉為秒數為1480550399。以上的代碼中,我將數據表分為9個區,從16年11月30日到17年06月31日 共8個區加上pnow這個區存放17年6月31日以后的數據;如上所示,16年11月30日以前的數據,將會存放在p161130這個分區中16年12月01日至16年12月31日的數據將會存放在p161231分區中,以此類推…
分區后可以執行以下語句查看效果(后面也可以用該語句查看每個分區中有多少數據):
SELECT PARTITION_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'table_name';
3、刪除一個分區:
執行語句:ALTER TABLE table_name DROP PARTITION p_name;
注意:刪除一個分區時,該分區內的所有數據也都會被刪除;
如果用這樣來刪除數據,要比用delete from table_name where …要有效得多;
4、新增一個分區:
執行語句:ALTER TABLE table_name ADD PARTITION (PARTITION p_name VALUES LESS THAN (xxxxxxxxx));
注意:如果原先最后一個分區是PARTITION pnow VALUES LESS THAN MAXVALUE; 那么應該先刪除該分區,然后在執行新增分區語句,然后再新增回該分區;