为了保证效率和质量,每篇文章发布6个知识点,由简单及难,我们继续Hbase的尾巴,并开始HIVE:
1)怎样将mysql的数据导入到hbase中?
A、一种可以加快批量写入速度的方法是通过预先创建一些空的regions,这样当数据写入hbase时,会按照region分区情况,在集群内做数据的负载均衡。
B、hbase 里面有这样一个hfileoutputformat类,他的实现可以将数据转换成hfile格式,通过new一个这个类,进行相关配置,这样会在Hdfs下面产生一个文件,这个时候利用hbase提供的jruby的loadtable.rb脚本就可以进行批量导入。
2)hbase的快速查找建立在哪些因素的基础上?
有且仅有一个:rowkey(行键),rowkey是hbase的key-value存储中的key,通常使用用户要查询的字段作为rowkey,查询结果作为value。可以通过设计满足几种不同的查询需求。
(1)数字rowkey的从大到小排序:原生hbase只支持从小到大的排序,这样就对于排行榜一类的查询需求很尴尬。那么采用rowkey = Integer.MAX_VALUE-rowkey的方式将rowkey进行转换,最大的变最小,最小的变最大。在应用层再转回来即可完成排序需求。
(2)rowkey的散列原则:如果rowkey是类似时间戳的方式递增的生成,建议不要使用正序直接写入rowkey,而是采用reverse的方式反转rowkey,使得rowkey大致均衡分布,这样设计有个好处是能将regionserver的负载均衡,否则容易产生所有新数据都在一个regionserver上堆积的现象,这一点还可以结合table的预切分一起设计。
3)简述 HBase 的瓶颈和oracle的瓶颈有什么不同?
HBase的瓶颈就是硬传输速度,Hbase 的操作,它可以往数据里面 insert,也可以update一些数据,但update 的实际上也是insert,只是插入一个新的时间戳的一行,delete数据,也是insert,只是insert一行带有delete标记的一行。hbase的所有操作都是追加插入操作。hbase是一种日志集数据库。它的存储方式,像是日志文件一样。它是批量大量的往硬盘中写,通常都是以文件形式的读写。这个读写速度,就取决于硬盘与机器之间的传输有多快。
而oracle的瓶颈是硬盘寻道时间。它经常的操作时随机读写。要update一个数据,先要在硬盘中找到这个block,然后把它读入内存,在内存中的缓存中修改,过段时间再回写回去。由于你寻找的block不通,这就存在一个随机的读。硬盘的寻道时间主要由转速来决定。而寻道时间,技术基本没有改变,这就形成了寻道时间瓶颈。
4)Hive 的 join 有几种方式,怎么实现 join 的?
3种join方式:
1)在reduce端进行join,最常用的join方式。
Map端的主要工作:为来自不同表(文件)的key/value打标签以区别不同来源的记录。然后
用连接字段作为key,其余部分和新加的标志作为value,最后进行输出。
reduce端的主要工作:在reduce端以连接字段作为key的分组已经完成,我们只需要在每一
个分组当中将那些来源于不同文件的记录(在map阶段已经打标志)分开,最后进行笛卡尔。
2)在map端进行join,使用场景:一张表非常小、一张表很大。
在提交作业的时候先将小表文件放到该作业的DistributedCache中,然后从DistributeCache中取出该小表进行join key / value解释分割放到内存中(可以放大Hash Map等等容器中)。然后扫描大表,看大表中的每条记录的join key /value值是否能够在内存中找到相同join key的记录,如果有则直接输出结果
3)SemiJoin。
semijoin就是左边连接是reducejoin的一种变种,在map端过滤掉一些数据,在网络传输过程中,只传输参与连接的数据,减少了shuffle的网络传输量,其他和reduce的思想是一样的。
实现:将小表中参与join的key单独抽取出来通过DistributeCache分发到相关节点,在map阶段扫描连接表,将join key不在内存hashset的纪录过滤掉,让参与join的纪录通过shuffle传输到reduce端进行join,其他和reduce join一样。
5)hive 内部表和外部表的区别?
Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。
6)hive 是如何实现分区的?建表语句: create table tablename (id) partitioned by (dt string) 增加分区: alter table tablenname add partition (dt = '2016-03-06') 删除分区: alter table tablename drop partition (dt = '2016-03-06')