----出差了一个月没时间写博客,一方面是自己犯懒了,不过最根本的还是出差的地方网络、环境都不好,工作量也大,导致自己没学到太多新的东西。唯一值得一提的就是对数据库中的分区表有了些了解,所以趁着这周在公司,记录下来吧
数据库也用了很久了,不过真正开始学着用分区表是最近才开始的。
刚开始用数据库的时候懂得不多,顶多建个索引一类的优化一下(ORACLE)。后来开始使用VERTICA,对分区表有了些了解,不过还没开始用。直到最近再用impala的时候,才真的开始对分区表研究起来。
分区表,顾名思义就是对表进行分区。通常数据库会把不同的分区物理上分隔开进行管理,这样做有很多优点:
- 可以提高查询的效率。查询的时候如果对用作分区的关键字来进行过滤的话(在WHERE中),那么就可以避免对全表进行扫描,节省磁盘IO。比如数据库中存储了近3年的数据,按月进行了分区,如果只查询某一个月的数据,就可以跳过35个不相关的分区,只要扫描一个分区就可以了。
- 可以提高删除的效率。比如经常见到的需要对过期数据进行删除时,如果用DELETE的话,那么要扫描全表才能完成这个操作。而如果表按时间进行了分区,那么只要把过期的分区DROP掉就可以了,效率比DELETE高的多
不过分区表这个机制、和应用,在不同数据库中是有挺大区别的。接下来我就自己已知的情况稍微总结一下。
ORACLE:支持不同的分区方式:范围分区、列表分区、哈希分区、范围-列表的混合分区等等。在ORACLE中,通常建议单表超过2GB就要进行分区处理了,毕竟ORACLE的存储是单机的,不能像MPP数据库那样并行读取。对数据进行分区可以极大的提高查询效率,而且不同的分区(貌似)可以分别备份和恢复。由于近期的分析都是在MPP数据库中完成的,所以没有针对ORACLE的分区做性能测试,但是在网上看到性能提升还是蛮大的。以后如果有闲的话,这块再补上。
VERTICA:这种列式的MPP数据库,一般都是对压缩很友好,但是对修改不友好的。VERTICA就是这样,它可以针对不同的列选择不同的压缩算法,使得压缩效果很好,但是却不能真的去修改或者删除数据。比如你如果想要删除数据,那么VERTICA只是在表中对这一行做个删除标记,但是数据却依然留在文件里。如果要某一行,实质的操作是把这一行做一个删除标记,然后再插入新的一行(也就是修改后的结果),以达到和修改相同的效果。MPP数据库中的单表通常都很大,比如存储了最近n年数以亿记的数据,当数据过期需要删除的时候,用DELETE显然效率会很低,而且也会影响之后的查询效率。如果对数据按照时间做了分区(如按月分区),那么只要把过期的数据删除掉就可以了。VERTICA的分区基本相当于ORACLE里面的列表分区,带有ORACLE11g 的Interval的分区效果(即随着数据的插入自动新增分区),不过因为支持使用表达式来计算分区关键字,所以也能实现类似ORACLE的范围分区。在VERTICA中关于分区提升查询性能的描述比较少,因为VERTICA的性能提升主要是依赖合理的SEGMENT分布数据,以及合理的PROJECTION设计来实现的,分区功能主要解决批量删的问题。另外:VERTICA要求用于分区的字段要有非空约束。
IMPALA:IMPALA中分区的功能基本是VERTICA和ORACLE的综合。因为IMPALA支持的是”类SQL”的操作,不支持DELETE等功能,所有的表只能插入数据,不能修改,所以只有通过分区才能实现删除表中的数据的功能。这点通过IMPALA的文件系统HDFS就可以大概理解,HDFS本身就是只支持文件的写入,不支持修改文件的,所以IMPALA自然也不能修改数据。但是数据分区以后,就可以通过对分区进行DROP操作来实现数据的删除。但是要注意的是,不同的分区存储在不同的子文件夹中,而对不同的文件做定位,本身就是一件消耗时间的事情。如果分区分得过多,每个分区数据量过少,那么也会对查询效率有影响(如果分区太多,当你需要对全表进行检索的时候,需要遍历的文件数量也会很多)。IMPALA也只支持列表分区,而且要求用于分区的关键字要是独立的字段。比如
create table t1 (i int) partitioned by (x int, y string);
这里是按照x、y来进行分区的,他们既可以是本来就存在于源数据中的某两个字段,也可以是两个从源数据中计算得到的用于分区的字段。比如:insert into t1 partition(x=10, y=’a’) select c1 from some_other_table;
insert into t1 partition(x, y=’b’) select c1, c2 from some_other_table;
第一句话是把t1=c1插入到x=10,y=’a’这个分区中,第二句话是把t1=c1插入到x=c2、y=’b’的分区中。同VERTICA一样,IMPALA也不能支持TIMESTAMP分区,所以通常用extract(year from xxx)*100+extract(month from xxx)(按月)或者extract(month from xxx)*100+extract(day from xxx)来进行分区。另外,由于分区存储在不同的路径中,分区列的取值可以通过路径推出而不需要存储在磁盘文件中,所以增加分区列并不会加大数据存储压力。
分区可以极大的增加数据查询、删除的效率,是个非常好的东西,只是分区要在建表的时候预先设计好。通常数据库都不支持建表后增加分区,能做到的方法基本也是新建一张分区表,然后把原表中的数据复制过去。
不知不觉该下班了,先写到这,以后再逐渐完善关于分区的理解。
P.S. VERTICA中有SEGMENT和PARTITION这么两个概念,前者用来决定数据在不同节点之间的分布,后者决定同一节点上数据的存储方式。这个等到以后有时间再补一片博客。