實戰mysql分區(PARTITION)

前些天拿到一個表,將近有4000w數據,沒有任何索引,主鍵。(建這表的絕對是我的才)mysql

這是一個日誌表,記錄了遊戲中物品的產出與消耗,原先有一個後臺對這個表進行統計。。。。。(這要用超級計算機才能統計得出來吧),只能幫前人填坑了。。。。sql

數據太大,決定用分區來重構。less

clipboard.png

若是你發現是empty,說明你的mysql版本不夠,分區至少要5.1函數

下面針對業務查詢,決定用時間來作range分區(還有list,hash等類型),一個月一個區.優化

按照RANGE分區的表是經過以下一種方式進行分區的,每一個分區包含那些分區表達式的值位於一個給定的連續區間內的行。這些區間要連續且不能相互重疊,使用VALUES LESS THAN操做符來進行定義。ui

新建一個表:spa

CREATE TABLE xxxxxxxx (
crttm int(11) NOT NULL,
srvid int(11) NOT NULL,
evtid int(11) NOT NULL,
aid int(11) NOT NULL,
rid int(11) NOT NULL,
itmid int(11) NOT NULL,
itmnum int(11) NOT NULL,
gdtype int(11) NOT NULL,
gdnum int(11) NOT NULL,
islmt int(11) NOT NULL,
KEY crttm (crttm),
KEY itemid (itmid),
KEY srvid (srvid),
KEY gdtype (gdtype)
) ENGINE=myisam DEFAULT CHARSET=utf8
PARTITION BY RANGE (crttm)
(
PARTITION p201303 VALUES LESS THAN (unix_timestamp('2013-04-01')),
PARTITION p201304 VALUES LESS THAN (unix_timestamp('2013-05-01')),
PARTITION p201305 VALUES LESS THAN (unix_timestamp('2013-06-01')),
PARTITION p201306 VALUES LESS THAN (unix_timestamp('2013-07-01')),
PARTITION p201307 VALUES LESS THAN (unix_timestamp('2013-08-01')),
PARTITION p201308 VALUES LESS THAN (unix_timestamp('2013-09-01')),
PARTITION p201309 VALUES LESS THAN (unix_timestamp('2013-10-01')),
PARTITION p201310 VALUES LESS THAN (unix_timestamp('2013-11-01')),
PARTITION p201311 VALUES LESS THAN (unix_timestamp('2013-12-01')),
PARTITION p201312 VALUES LESS THAN (unix_timestamp('2014-01-01')),
PARTITION p201401 VALUES LESS THAN (unix_timestamp('2014-02-01'))
);unix

注意:日誌

  1. primary key和unique key必須包含在分區key的一部分,不然在建立primary key和unique index時會報」ERROR 1503 (HY000)「

mysql> create unique index idx_employees1_job_code on employees1(job_code);
ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function

mysql> ALTER TABLE skate.employees1 ADD PRIMARY KEY (id) ;
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning functioncode

  1. 範圍分區添加分區只能在最大值後面追加分區
  2. 全部分區的engine必須同樣
  3. 範圍分區分區字段:integer、數值表達式、日期列,日期函數表達式(如year(),to_days(),to_seconds(),unix_timestamp())

將舊的表數據導入到新表後,看到新表的數據都分佈到不一樣的區了!

clipboard.png

維護命令:

添加分區

alter table xxxxxxx add partition (partition p0 values less than(1991)); //只能添加大於分區鍵的分區

刪除分區

alter table xxxxxxx drop partition p0; //能夠刪除任意分區

刪除分區數據

alter table xxxxxx truncate partition p1,p2;
alter table xxxxxx truncate partition all;

delete from xxxxxx where separated < '2006-01-01' or (separated >= '2006-01-01' and separated<'2011-01-01');

重定義分區(包括重命名分區,伴隨移動數據;合併分區)

alter table xxxxx reorganize partition p1,p3,p4 into (partition pm1 values less than(2006),
partition pm2 values less than(2011));

rebuild重建分區

alter table xxxxxx rebuild partition pm1/all; //至關於drop全部記錄,而後再reinsert;能夠解決磁盤碎片

優化表

alter table tt2 optimize partition pm1; //在大量delete表數據後,能夠回收空間和碎片整理。但在5.5.30後支持。在5.5.30以前能夠經過recreate+analyze來替代,若是用rebuild+analyze速度慢

analzye表

alter table xxxxxx analyze partition pm1/all;

check表

alter table xxxxxx check partition pm1/all;

show create table employees2; //查看分區表的定義
show table status like 'employees2'G; //查看錶時候是分區表 如「Create_options: partitioned」
select * from information_schema.KEY_COLUMN_USAGE where table_name='employees2'; //查看索引
SELECT * FROM information_schema.partitions WHERE table_name='employees2' //查看分區表
explain partitions select * from employees2 where separated < '1990-01-01' or separated > '2016-01-01'; //查看分區是否被select使用

zhuzy

相關文章
相關標籤/搜索