Review(6)

9.Hive内部表和外部表区别

 

Hive创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。

在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。

这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享元数据。

建内部表

    create table student(Sno int,Sname string,Sex string,Sage int,Sdept string)row format delimited fields terminated by ',';

建外部表

    create external table student_ext(Sno int,Sname string,Sex string,Sageint,Sdept string)row format delimited fields terminated by',' location '/stu';

10.Hive外部表 有静态 动态 区别是什么?

Hive的分区方式:由于Hive实际是存储在HDFS上的抽象,Hive的一个分区名对应一个目录名,子分区名就是子目录名,并不是一个实际字段。

当我们在插入数据的时候指定分区,其实就是新建一个目录或者子目录,或者在原有的目录上添加数据文件。

Hive分区是在创建表的时候用Partitioned by 关键字定义的,但要注意,Partitioned by子句中定义的列是表中正式的列,但是Hive下的数据文件中并不包含这些列,因为它们是目录名。

静态分区

创建一张静态分区表par_tab,单个分区

create table par_tab (name string,nation string) partitioned by (sex string) row format delimited fields terminated by ',';

这时候通过desc查看的表结构如下

准备本地数据文件par_tab.txt,内容 “名字/国籍”,将以性别(sex)作为分区

jan,china
mary,america
lilei,china
heyong,china
yiku,japan
emoji,japan

把数据插入到表(其实load操作相当于把文件移动到HDFS的Hive目录下)

load data local inpath '/home/hadoop/files/par_tab.txt' into table par_tab partition (sex='man');

 

 

因为分区列是表实际定义的列,所以查询分区数据时

hive> select * from par_tab where sex='woman';
OK
lily    china    woman
nancy    china    woman
hanmeimei    america    woman
Time taken: 0.515 seconds, Fetched: 3 row(s)

下面创建一张静态分区表par_tab_muilt,多个分区(性别+日期)

hive> create table par_tab_muilt (name string, nation string) partitioned by (sex string,dt string) row format delimited fields terminated by ',' ;
hive> load data local inpath '/home/hadoop/files/par_tab.txt' into table par_tab_muilt partition (sex='man',dt='2017-03-29');


[hadoop@hadoop001 files]$ hadoop dfs -lsr /user/hive/warehouse/par_tab_muilt
drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:45 /user/hive/warehouse/par_tab_muilt/sex=man
drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:45 /user/hive/warehouse/par_tab_muilt/sex=man/dt=2017-03-29
-rwxr-xr-x   1 hadoop supergroup         71 2017-03-29 08:45 /user/hive/warehouse/par_tab_muilt/sex=man/dt=2017-03-29/par_tab.txt

可见,新建表的时候定义的分区顺序,决定了文件目录顺序(谁是父目录谁是子目录),正因为有了这个层级关系,当我们查询所有man的时候,man以下的所有日期下的数据都会被查出来。如果只查询日期分区,但父目录sex=man和sex=woman都有该日期的数据,那么Hive会对输入路径进行修剪,从而只扫描日期分区,性别分区不作过滤(即查询结果包含了所有性别)。

动态分区

如果用上述的静态分区,插入的时候必须首先要知道有什么分区类型,而且每个分区写一个load data,太烦人。使用动态分区可解决以上问题,其可以根据查询得到的数据动态分配到分区里。其实动态分区与静态分区区别就是不指定分区目录,由系统自己选择。

首先,启动动态分区功能

hive> set hive.exec.dynamic.partition=true;

假设已有一张表par_tab,前两列是名称name和国籍nation,后两列是分区列,性别sex和日期dt,数据如下

hive> select * from par_tab;
OK
lily    china    man    2013-03-28
nancy    china    man    2013-03-28
hanmeimei    america    man    2013-03-28
jan    china    man    2013-03-29
mary    america    man    2013-03-29
lilei    china    man    2013-03-29
heyong    china    man    2013-03-29
yiku    japan    man    2013-03-29
emoji    japan    man    2013-03-29
Time taken: 1.141 seconds, Fetched: 9 row(s)

现在我把这张表的内容直接插入到另一张表par_dnm中,并实现sex为静态分区,dt动态分区(不指定到底是哪日,让系统自己分配决定)

hive> insert overwrite table par_dnm partition(sex='man',dt)
    > select name, nation, dt from par_tab;

 

 注意,动态分区不允许主分区采用动态列而副分区采用静态列,这样将导致所有的主分区都要创建副分区静态列所定义的分区。

 

动态分区可以允许所有的分区列都是动态分区列,但是要首先设置一个参数hive.exec.dynamic.partition.mode :

hive> set hive.exec.dynamic.partition.mode;
hive.exec.dynamic.partition.mode=strict

它的默认值是strict,即不允许分区列全部是动态的,这是为了防止用户有可能原意是只在子分区内进行动态建分区,但是由于疏忽忘记为主分区列指定值了,这将导致一个dml语句在短时间内创建大量的新的分区(对应大量新的文件夹),对系统性能带来影响。
所以我们要设置:

hive> set hive.exec.dynamic.partition.mode=nostrict;

 

11.Hive UDF 函数,如何永久生效 

    1.在$HIVE_CONF_DIR/下添加文件.hiverc

      在文件中添加udf函数

     add  jar  ***.jar

    create temporary funcation **** as ***

    2.在hive-env.sh配置文件中添加HIVE_AUX_JARS_PATH

    然后再使用

    3.下载对应的hive源码包重新编译打包

临时注册

  1、将导出的hiveudf.jar复制到hdfs上
   hadoop fs -copyFromLocal hiveudf.jar hiveudf.jar
  2、进入hive,添加jar,
add jar hdfs://localhost:9000/user/root/hiveudf.jar
  3、创建一个临时函数
create temporary function my_lower as 'com.example.hive.udf.LowerCase';
4、调用
   select LowerCase(name) from teacher;
  注:这种方法只能添加临时的函数,每次重新进入hive的时候都要再执行4-6
 

12.Hive 的sort by、order by、cluster by、Distribute by 各代表什么意思

  orderby:会对输入做全局排序,因此只有一个reducer(多个reducer无法保证全局有序)。只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。

sort by:不是全局排序,其在数据进入reducer前完成排序。

distribute by:按照指定的字段对数据进行划分输出到不同的reduce中。

cluster by:除了具有distribute by的功能外还兼具sort by的功能。

13 sqoop 如何增量抽取到Hive,对应Hive表如何设计

每隔两分钟增量导入数据

#!/bin/sh

export SQOOP_HOME=/usr/share/sqoop-1.4.4

hostname="192.168.1.199"

user="root"

password="root"

database="test"

table="tags"

curr_max=0

function db_to_hive(){
 
    ${SQOOP_HOME}/bin/sqoop import --connect jdbc:mysql://${hostname}/${database} --username ${user} --password ${password}  --table ${table}   --split-by docid --hive-import --hive-table lan.ding  
 --fields-terminated-by '\t' --incremental  append  --check-column docid --last-value ${curr_max}   
    result=`mysql -h${hostname} -u${user} -p${password} ${database}<<EOF 
select max(docid) from ${table};
EOF`
curr_max=`echo $result |awk '{print $2}'`
}
 
if [ $# -eq 0 ];then
    while true
    do
      db_to_hive
      sleep 120
    done
    exit
fi
https://blog.csdn.net/sprita1/article/details/42676307

sqoop import \
--connect jdbc:mysql://192.168.52.130:3306/sqoop \
--username root \
--password 123456 \
-m 1 \
--table emp \
--hive-database 'ruozedata_test' \
--hive-import \
--direct \
--hive-table 'emp_sqopp_test' \
--fields-terminated-by '\t' \
--input-null-non-string '0' \
--input-null-string '' \
--check-column empno \
--incremental append \
--last-value 9999

14Hbase 的rowkey如何设计?请举例

rowkey设计三原则:    1.散列原则(hash打散),2.长度原则(不能太长),3.唯一性(RowKey需要唯一确定一条数据,所以必须唯一)

 rowkey长度原则

rowkey是一个二进制码流,可以是任意字符串,最大长度64kb,实际应用中一般为10-100bytes,以byte[]形式保存,一般设计成定长。

建议越短越好,不要超过16个字节,原因如下:

  • 数据的持久化文件HFile中是按照KeyValue存储的,如果rowkey过长,比如超过100字节,1000w行数据,光rowkey就要占用100*1000w=10亿个字节,将近1G数据,这样会极大影响HFile的存储效率;

  • MemStore将缓存部分数据到内存,如果rowkey字段过长,内存的有效利用率就会降低,系统不能缓存更多的数据,这样会降低检索效率。

 rowkey散列原则

如果rowkey按照时间戳的方式递增,不要将时间放在二进制码的前面,建议将rowkey的高位作为散列字段,由程序随机生成,低位放时间字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息,所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率。

rowkey唯一原则

必须在设计上保证其唯一性,rowkey是按照字典顺序排序存储的,因此,设计rowkey的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块。

什么是热点

HBase中的行是按照rowkey的字典顺序排序的,这种设计优化了scan操作,可以将相关的行以及会被一起读取的行存取在临近位置,便于scan。然而糟糕的rowkey设计是热点的源头。

热点发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)。大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚至region不可用,这也会影响同一个RegionServer上的其他region,由于主机无法服务其他region的请求。

设计良好的数据访问模式以使集群被充分,均衡的利用。为了避免写热点,设计rowkey使得不同行在同一个region,但是在更多数据情况下,数据应该被写入集群的多个region,而不是一个。

下面是一些常见的避免热点的方法以及它们的优缺点:

加盐

这里所说的加盐不是密码学中的加盐,而是在rowkey的前面增加随机数,具体就是给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同。分配的前缀种类数量应该和你想使用数据分散到不同的region的数量一致。加盐之后的rowkey就会根据随机生成的前缀分散到各个region上,以避免热点。

哈希

哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的rowkey,可以使用get操作准确获取某一个行数据

反转

第三种防止热点的方法时反转固定长度或者数字格式的rowkey。这样可以使得rowkey中经常改变的部分(最没有意义的部分)放在前面。这样可以有效的随机rowkey,但是牺牲了rowkey的有序性。

反转rowkey的例子以手机号为rowkey,可以将手机号反转后的字符串作为rowkey,这样的就避免了以手机号那样比较固定开头导致热点问题

时间戳反转

一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为rowkey的一部分对这个问题十分有用,可以用 Long.Max_Value - timestamp 追加到key的末尾,例如 [key][reverse_timestamp] , [key] 的最新值可以通过scan [key]获得[key]的第一条记录,因为HBase中rowkey是有序的,第一条记录是最后录入的数据。

比如需要保存一个用户的操作记录,按照操作时间倒序排序,在设计rowkey的时候,可以这样设计:

[userId反转][Long.Max_Value - timestamp],在查询用户的所有操作记录数据的时候,直接指定反转后的userId,startRow是[userId反转][000000000000],stopRow是[userId反转][Long.Max_Value - timestamp]

如果需要查询某段时间的操作记录,startRow是[user反转][Long.Max_Value - 起始时间],stopRow是[userId反转][Long.Max_Value - 结束时间]

其他一些建议

尽量减少行和列的大小在HBase中,value永远和它的key一起传输的。当具体的值在系统间传输时,它的rowkey,列名,时间戳也会一起传输。如果你的rowkey和列名很大,甚至可以和具体的值相比较,那么你将会遇到一些有趣的问题。HBase storefiles中的索引(有助于随机访问)最终占据了HBase分配的大量内存,因为具体的值和它的key很大。可以增加block大小使得storefiles索引再更大的时间间隔增加,或者修改表的模式以减小rowkey和列名的大小。压缩也有助于更大的索引。

列族尽可能越短越好,最好是一个字符

15hbase的读写流程经过master吗?假如不经过 那么什么流程经过?

 

   读写过程

                读过程

                    (1) 客户端通过zookeeper以及root表和meta表找到目标数据所在的regionserver

                    (2)联系regionserver查询目标数据

                    (3)regionserver定位到目标数据所在的region,发出查询请求

                    (4)region先在memstore中查找,命中则返回

                    (5)如果在memstore中找不到,则在storefile中扫描(可能会扫描到很多的storefile----bloomfilter布隆过滤器)

                    补充:布隆过滤器参数类型有2种:

                    Row、row+col

                写过程

                    (1)client向region server提交写请求

                    (2)region server找到目标region

                    (3)region检查数据是否与schema一致

                    (4)如果客户端没有指定版本,则获取当前系统时间作为数据版本

                    (5)将更新写入WAL log

                    (6)将更新写入Memstore(内存)

                    (7)判断Memstore的是否需要flush为StoreFile文件。

                细节描述:

                        hbase使用MemStore和StoreFile存储对表的更新。

                        数据在更新时首先写入Log(WAL log)和内存(MemStore)中,MemStore中的数据是排序的,

                    ***当MemStore累计到一定阈值时,就会创建一个新的MemStore,

                    ***并且将老的MemStore添加到flush队列,由单独的线程flush到磁盘上,成为一个StoreFile。

                    于此同时,系统会在zookeeper中记录一个redo point,表示这个时刻之前的变更已经持久化了。

                    当系统出现意外时,可能导致内存(MemStore)中的数据丢失,此时使用Log(WAL log)来恢复checkpoint之后的数据。

                    ***StoreFile是只读的,一旦创建后就不可以再修改。因此Hbase的更新其实是不断追加的操作。当一个Store中的

                    StoreFile达到一定的阈值后,就会进行一次合并(minor_compact, major_compact),将对同一个key的修改合并到一起,

                    形成一个大的StoreFile,当StoreFile的大小达到一定阈值后,又会对 StoreFile进行split,等分为两个StoreFile。

                                        ***由于对表的更新是不断追加的,compact时,需要访问Store中全部的 StoreFile和MemStore,将他们按row key进行合并,

                    由于StoreFile和MemStore都是经过排序的,并且StoreFile带有内存中索引,合并的过程还是比较快。

  经过Master的请求

  

    Master:

                    1 为Region server分配region

                    2 负责region server的负载均衡

                    3 发现失效的region server并重新分配其上的region

                    4 HDFS上的垃圾文件回收

                    5 处理schema更新请求

16hbase的hbck命令有了解吗 ?哪些故障 哪些命令 

 

通常在hbase重启的时候会出现数据不一致的问题,就会用到hbck detail查看详细信息进行修复。但是避免使用hbck repair,这个有风险。

     hbck是hbase里用来检测 region一致性,表完整性问题及修复损坏的命令行工具。它有2种工作模式:

只读不一致性识别模式(默认模式,但不尝试修复)

多阶段读写修复模式 (如果发现错误,则尝试修复)

注:如果只检查特定的表 则用: hbck ..

常用选项:

1. -details 顾名词义,打印详细结果

2. -fix 用来修复region级别的不一致性。其内部的操作顺序如下

先查是否存在不一致的。

如有表级别的不一致性,则先修复表的不一致问题。

如有region级别的不一致性,则修复该级别的问题。在修复期间region是关闭状态

也可以通过其它方式来修复不一致性,如下:

-fixAssignments repairs unassigned, incorrectly assigned or multiply assigned regions. 修复没有分配的,已分配但不正确的单个region或者多个region。

-fixMeta removes rows from hbase:meta when their corresponding regions are not present in HDFS and adds new meta rows if regions are present in HDFS but not in hbase:meta. 当从hbase:meta表相关的region在hdfs里没有找到,则移除这些行。如果这些region在hdfs里,则在hbase.meta里增加新的行

-repairHoles creates HFiles for new empty regions on the filesystem and ensures that the new regions are consistent. 在空的region里新建一个HFiles,却表新的region是一致的。

-fixHdfsOrphans repairs a region directory that is missing a region metadata file (the .regioninfo file).在region目录里 修复那些缺失region元数据的文件如(.regioninfo)

-fixHdfsOverlaps fixes overlapping regions. You can further tune this argument using the following options: 修复重叠的regions。与此同时结合以下选项:

-maxMerge controls the maximum number of regions to merge. 控制最大合并region的数量。

-sidelineBigOverlaps attempts to sideline the regions which overlap the largest number of other regions. 尝试退出那些与其它region有最大数量的重叠的region

-maxOverlapsToSideline limits the maximum number of regions to sideline. 限制退出region的最大数量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值