Chinaunix首页 | 论坛 | 博客
  • 博客访问: 541231
  • 博文数量: 76
  • 博客积分: 2990
  • 博客等级: 少校
  • 技术积分: 827
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-26 10:53
文章分类

全部博文(76)

文章存档

2011年(47)

2010年(13)

2009年(5)

2008年(11)

分类: Mysql/postgreSQL

2011-07-05 09:15:47

前言:在生产库下对一个1000万行的表进行分区,经过分析,根据ctime(datetime)字段RANGE型按月进行分区.该表特点:
1.闲时每分钟产生约100行数据
2.只有insert修改,select查询,没有delete,update,replace等修改
3.有一列自增列
4 .   数据库版本Percona-Server-5.1.57-rel12.8-232-Linux-x86_64

从未分区到分区的迁移方案.如下:

db_name="production"

# 找出当前位置,导出当前的表
mark_id=`mysql  $db_name -e "select max(id) from production_tb;"`
mysqldump  --default-character-set=utf8  $db_name  production_tb > production_tb.sql

#   建立分区表 , 禁止索引
mysql --default-character-set=utf8  $db_name <CREATE TABLE production_tb_partition (
  id int(8) NOT NULL AUTO_INCREMENT,
  ctime datetime NOT NULL,
  ip bigint(20) DEFAULT NULL,
  country varchar(255) DEFAULT NULL,
  http_host varchar(100) DEFAULT NULL,
  http_referer varchar(255) NOT NULL,
  server_id smallint(4) NOT NULL,
  source varchar(20) DEFAULT NULL,
  medium varchar(20) DEFAULT NULL,
  term varchar(20) DEFAULT NULL,
  content varchar(20) DEFAULT NULL,
  campaign varchar(40) DEFAULT NULL,
  code varchar(10) DEFAULT NULL,
  sub_id varchar(10) DEFAULT NULL,
  session_id varchar(50) NOT NULL,
  keyword varchar(255) NOT NULL,
  PRIMARY KEY (id,ctime),   #分区列必须是主键
  KEY idx_source_subid (source,sub_id),
  KEY idx_reg_time (ctime),
  KEY idx_source (source),
  KEY idx_click_ip (ip)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8
PARTITION BY RANGE (to_days(ctime))
(
PARTITION p201012 VALUES LESS THAN (to_days('2011-01-01')),
PARTITION p201101 VALUES LESS THAN (to_days('2011-02-01')) ,
PARTITION p201102 VALUES LESS THAN (to_days('2011-03-01')) ,
PARTITION p201103 VALUES LESS THAN (to_days('2011-04-01')) ,
PARTITION p201104 VALUES LESS THAN (to_days('2011-05-01')) ,
PARTITION p201105 VALUES LESS THAN (to_days('2011-06-01')) ,
PARTITION p201106 VALUES LESS THAN (to_days('2011-07-01')) ,
PARTITION p201107 VALUES LESS THAN (to_days('2011-08-01')) ,
PARTITION p201108 VALUES LESS THAN (to_days('2011-09-01')) ,
PARTITION p201109 VALUES LESS THAN (to_days('2011-10-01')) ,
PARTITION p201110 VALUES LESS THAN (to_days('2011-11-01')),
PARTITION p201111 VALUES LESS THAN (to_days('2011-12-01')),
PARTITION p201112 VALUES LESS THAN (to_days('2012-01-01')),
PARTITION pmax VALUES LESS THAN MAXVALUE );
ALTER TABLE production_tb_partition DISABLE KEYS;
EOF

# dump出来的文件, 只保留insert语句,更改表名
grep -i insert production_tb.sql > production_tb_partition.sql
sed -i -e "s%production_tb%production_tb_partition%g"  production_tb_partition.sql
time mysql --default-character-set=utf8  $db_name <  production_tb_partition.sql

# 分区表重命名为正式表
rename table production_tb to  production_tb_nopart;
rename table production_tb_partition to production_tb;

#  在会话中锁定正式表只读,将新数据库导入正式表
LOCK TABLES production_tb  READ;
insert into  production_tb
  select  * from production_tb_nopart where id > $mark_id;
unlock tables;

# enable正式表的key
ALTER TABLE production_tb_partition ENABLE KEYS;

备注 :
1.效率问题
  a.直接alter为分区表 (未分区前ctime不是主键,无法测试)
  b.新表 insert前 未 disable key   72min
  c.新表insert前 disable key    10min (本方案)
2. 之前效率问题测试引发的数据存储问题
  explain同一个查询,a方案,b方案,c方案 ,扫描到的行数不同.
  a方案 424964 rows
      b方案  322415 rows
      c方案  231766 rows
阅读(4650) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~