Chinaunix首页 | 论坛 | 博客
  • 博客访问: 950464
  • 博文数量: 83
  • 博客积分: 32
  • 博客等级: 民兵
  • 技术积分: 2080
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-12 09:45
个人简介

努力学习,努力分享,努力.....在努力..努力离开..

文章分类

全部博文(83)

文章存档

2017年(3)

2015年(1)

2014年(47)

2013年(32)

分类: Mysql/postgreSQL

2013-10-26 22:18:44

可用性增强:truncate分区


分区最吸引人的一个功能是瞬间移除大量记录的能力,DBA都喜欢将历史记录存储到按日期分区的分区表中,这样可以定期删除过时的历史数据,这种方法相当管用,假设第一个分区存储的是最旧的历史记录,那么你可以直接删除第一个分区,然后再在末尾建立一个新分区保存最近的历史记录,这样循环下去就可以实现历史记录的快速清除。


但当你需要移除分区中的部分数据时,事情就不是那么简单了,删除分区没有问题,但如果是清空分区,就很头痛了,要移除分区中的所有数据,但需要保留分区本身,你可以:


使用DELETE语句,但我们知道DELETE语句的性能都很差。


使用DROP PARTITION语句,紧跟着一个EORGANIZE PARTITIONS语句重新创建分区,但这样做比前一个方法的成本要高出许多。


MySQL 5.5引入了TRUNCATE PARTITION,它和DROP PARTITION语句有些类似,但它保留了分区本身,也就是说分区还可以重复利用。TRUNCATE PARTITION应该是DBA工具箱中的必备工具。


微调功能:TO_SECONDS


分区增强包有一个新的函数处理DATE和DATETIME列,使用TO_SECONDS函数,你可以将日期/时间列转换成自0年以来的秒数,如果你想使用小于1天的间隔进行分区,那么这个函数就可以帮到你。


TO_SECONDS会触发分区修整,与TO_DAYS不同,它可以反过来使用,就是FROM_DAYS,对于TO_SECONDS就没有这样的反向函数了,但要自己动手DIY一个也不是难事。


drop function if exists from_seconds;    
delimiter //    
create function from_seconds (secs bigint)    
returns DATETIME    
begin   
    declare days INT;    
    declare secs_per_day INT;    
    DECLARE ZH INT;    
    DECLARE ZM INT;    
    DECLARE ZS INT;    
    set secs_per_day = 60 * 60 * 24;    
    set days = floor(secs / secs_per_day);    
    set secssecs = secs - (secs_per_day * days);    
    set ZH = floor(secs / 3600);    
    set ZM = floor(secs / 60) - ZH * 60;    
    set ZS = secs - (ZH * 3600 + ZM * 60);    
    return CAST(CONCAT(FROM_DAYS(days), ' ', ZH, ':', ZM, ':', ZS) as DATETIME);    
end //    
delimiter ;  
有了这些新武器,我们可以有把握地创建一个小于1天的临时分区,如:


CREATE TABLE t2 (    
  dt datetime    
)    
PARTITION BY RANGE (to_seconds(dt))    
(    
  PARTITION p01 VALUES LESS THAN (to_seconds('2009-11-30 08:00:00')) ,    
  PARTITION p02 VALUES LESS THAN (to_seconds('2009-11-30 16:00:00')) ,    
  PARTITION p03 VALUES LESS THAN (to_seconds('2009-12-01 00:00:00')) ,    
  PARTITION p04 VALUES LESS THAN (to_seconds('2009-12-01 08:00:00')) ,    
  PARTITION p05 VALUES LESS THAN (to_seconds('2009-12-01 16:00:00')) ,    
  PARTITION p06 VALUES LESS THAN (MAXVALUE)    
);    
show create table t2\G    
*************************** 1. row ***************************    
Table: t2    
Create Table: CREATE TABLE `t2` (    
  `dt` datetime DEFAULT NULL   
) ENGINE=MyISAM DEFAULT CHARSET=latin1    
/*!50500 PARTITION BY RANGE (to_seconds(dt))    
(PARTITION p01 VALUES LESS THAN (63426787200) ENGINE = MyISAM,    
PARTITION p02 VALUES LESS THAN (63426816000) ENGINE = MyISAM,    
PARTITION p03 VALUES LESS THAN (63426844800) ENGINE = MyISAM,    
PARTITION p04 VALUES LESS THAN (63426873600) ENGINE = MyISAM,    
PARTITION p05 VALUES LESS THAN (63426902400) ENGINE = MyISAM,    
PARTITION p06 VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */  
因为我们没有使用COLUMNS关键字,我们也不能使用它,因为它不支持混合列和函数,表定义中的记录值就是TO_SECONDS函数的计算结果。


但我们还是要感谢新的函数,我们可以反推这个值,换算成一个更容易读懂的日期。


select   
  partition_name part,    
  partition_expression expr,    
  from_seconds(partition_description) descr,    
  table_rows    
FROM   
INFORMATION_SCHEMA.partitions    
WHERE   
    TABLE_SCHEMA = 'test'   
    AND TABLE_NAME='t2';    
+------+----------------+---------------------+------------+    
| part | expr           | descr               | table_rows |    
+------+----------------+---------------------+------------+    
| p01  | to_seconds(dt) | 2009-11-30 08:00:00 |          0 |    
| p02  | to_seconds(dt) | 2009-11-30 16:00:00 |          0 |    
| p03  | to_seconds(dt) | 2009-12-01 00:00:00 |          0 |    
| p04  | to_seconds(dt) | 2009-12-01 08:00:00 |          0 |    
| p05  | to_seconds(dt) | 2009-12-01 16:00:00 |          0 |    
| p06  | to_seconds(dt) | 0000-00-00 00:00:00 |          0 |    
+------+----------------+---------------------+------------+  

转自51CTO

阅读(2801) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~