Hive知识点

Hive

hive的概念

  • hive由于解决海量结构化日志的数据统计。
  • hive是基于hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类sql查询功能
  • 本质:将hql转化成MapReduce程序
  • hive处理的数据存储在hdfs上
  • hive分析数据底层的默认实现是MapReduce
  • 执行程序运行在yarn上

hive的优缺点

  • 优点
    • 操作接口采用类sql语法,提供快速开发的能力
    • 避免写MapReduce,减少开发人员的学习成本
    • hive的执行延迟高,常用于数据分析,对实时性要求不高的场合
    • hive的优势在于处理大数据,对于小数据没有优势,因为hive的执行延迟比较高
    • hive支持用户自定义函数
  • 缺点
    • hive的HQL表达能力有限
      • 迭代式计算无法表达
      • 数据挖掘方面不擅长
    • hive的效率比较低
      • hive的底层是mr
      • hive的调优比较困难,粒度较粗

Hive架构原理

  • 用户接口:client(hive shell、jdbc、webUI)
  • 元数据:metastore
    • 元数据包含:表名、表所属的数据库、表的 拥有者、列和分区的字段、表的类型、表的数据所在目录等
  • hadoop:使用hdfs进行存储,使用mr进行计算
  • 驱动器(driver):分析器、编译器、优化器、执行器
    • 分析器:将sql字符串转换成抽象语法树AST,这一步一般都用第三方工具库完成的。比如antlr:对AST进行语法分析,判断:表是否存在,字段是否存在、sql语义是否有误
    • 编译器:将AST编译成逻辑执行计划
    • 优化器:对逻辑执行计划进行优化
    • 执行器:把逻辑执行计划转换成可以运行的物理计划。即mr
  • hive通过给用户提供的一系列交互式接口,接收用户的sql指令,使用自己的driver,结合元数据,将这些指令转换为MapReduce,提交到yarn执行,最后返回结果输出到用户交互接

hive和数据库的比较

  • hive和数据库除了拥有类似的查询语言,再无类似之处
  • 数据库可以应用在online的应用中,但是hive是为了数据仓库而设计的
  1. 查询语言:HQL(类sql)
  2. 数据存储位置:hdfs上,而数据库存在块设备或者本地文件系统中
  3. 数据更新:hive由于是为数据仓库设计的,而数据仓库的内容是读多写少的。因此,hive不建议对数据的改写,所有的数据都是在加载的时候确定好的。 而数据库用insert into添加数据,update set修改数据
  4. 索引:hive在家在数据的过程中不会对数据进行任何处理,甚至不会对数据进行扫描,因此没有对数据中的某些key建立索引。由于MapReduce的引入,hive可以并行访问数据,即使没有索引,在大数据量的访问,hive仍然可以体现出优势。 数据库往往会针对列建立索引,因此在少量特定条件的数据访问,数据库可以有很高的效率,较低的延迟。
  5. 执行:大多数查询的执行都是通过hadoop提供的MapReduce来实现的。 而数据库通常有自己的执行引擎。
  6. 执行延迟:hive没有索引,需要全表扫描,因此延迟高。另外hive的底层是MapReduce框架,也快不了。但是MapReduce有并发的优势,在大数据的情况下就有优势了
  7. 可扩展:hive可以无限扩展,但是数据库扩展却非常有限
  8. 数据规模:hive支持很大的规模 数据库支持的数据规模较小

  • hive的元数据信息默认存储在自带的derby数据库中。

常用交互命令

  • hive -e “sql语句;”
  • hive -f “sql文件”
  • shell中 >是表示追加,>>是覆盖
  • 在hive里面查看hdfs文件系统:dfs shell命令
  • 查看本地文件系统:! shell命令;
  • 到根目录下查看./hivehistory文件可以看到所有历史命令

hive数据仓库位置配置

  • 默认位置在/usr/hive/warehouse路径下
  • 在仓库目录下,没有对默认的数据库创建文件夹。如果某张表属于default库,直接在数据仓库目录下创建一个文件夹
  • 可以在hive-default.xml文件修改数据仓库的路径;
  • log存放日志可以到hive-log4j.properties文件修改

数据类型

分隔符设置

  • row format delimited fields terminated by ‘,’ :列分隔符
  • collection items terminated by ‘_’ :map和array和struct的分隔符
  • map keys terminated by ‘:’ :map中的key和value的分隔符
  • lines terminated by ‘\n’ :行分隔符
  • map,struct和array里的元素间关系都可以用同一个字符表示

类型转换

  • hive的原子数据类型是可以进行隐式转换的。也可以用cast操作进行强制转换
  • 隐式转换规则:
    • 任何整数类型都可以隐式地转换为一个范围更广的类型,如tinyint可以转换为int,int转换为bigint
    • 所有整数类型、float和string类型都可以隐式的转换成double
    • tinyint、smallint、int都可以转换成float
    • boolean类型不可以转换成任何其他类型
  • cast强转
    • cast(“1” as int)
    • 强转如果失败,返回的是空值null

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

  • 删除数据时,内部表的元数据和真实数据会被一起删除;而外部表只会删除元数据,不删除真实数据

  • like允许用户复制现有的表结构,但是不复制数据

  • 加载数据:load data [local] inpath ‘dir’ into table tablename

  • 内外表转换:alter table tablename set talproperties(‘EXTERNAL’ = ‘TRUE/FALSE’)

  • 查看表的类型:desc formatted tablename


分区表(partitioned by)

  • 分区表对应一个hdfs文件系统上的独立文件夹,该文件夹是分区的所有的数据文件。
  • hive的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集
  • 查询用where分区值可以只查固定的分区的数据,而不用查询全部数据。如果不用where,则是全表扫描
  • 分区字段随便选
  • 加载数据到固定分区:load data local inpath ‘dir’ into table tablename partition(分区字段=分区取值)

数据从hdfs导出到本地文件系统

  • hadoop中的get
  • hive -e “sql语句” > 本地路径

分桶

  • 分区针对的是数据的存储路径;分桶针对的是数据文件
  • 分桶需要设置参数:开启支持分桶
  • tablesample(bucket x out of y on column)
    • y 必须是 table 总 bucket 数的倍数或者因子。hive 根据 y 的大小,决定抽样的比例。例如,table 总共分了 4 份,当 y=2 时,抽取(4/2=)2 个 bucket 的数据,当 y=8 时,抽取4/8=)1/2
      个 bucket 的数据
    • x:从哪个bucket开始抽取
    • y:桶数/y 表示抽取多少个bucket
    • x必须小于等于y的值

常用查询函数

  • NVL:给值为null的数据赋值,她的格式是NVL(string1,replace_with)。功能:如果string1为null,则NVL函数返回replace_with的值,否则返回string1的值。

时间类函数

  • data_format:格式化时间。格式为:date_format(‘2020-12-20’,‘yyyy-MM-dd’)=>转换为yyyy-MM-dd的格式
  • date_add:时间和天数相加。格式为:date_add(“2020-12-20”,天数);结果:返回2020-12-20加上天数的日期
  • date_sub:时间和天数相减
  • date_diff:两个时间相减。格式为:date_diff(“2020-12-20”,“2020-12-01”);返回两个日期相减得到的天数
  • next_day:下周一的日期。格式:next_day(‘2020-12-20’,‘Monday’);第二个参数为返回下周几,不固定是周一的
  • last_day:本月最后一天。格式:last_day(‘2020-12-20’)
  • case when:case 属性 when 匹配值1 then 返回值1 else 返回值2 end。

行转列

  • concat(string1/col1,string2/col2…):返回输入字符串连接后的结果,支持任意个输入
  • concat_ws(separator,str1,str2,…):是特殊形式的concat,以separator为连接符,连接字符串
  • collect_set(col):该函数只接受基本数据类型,主要作用是将某字段的值进行去重汇总。返回结果是一个数组类型字段

列转行

  • explode(col):将hive一列中复杂的array或者map结构拆分为多行。
  • LATERAL VIEW:
    • 用法:lateral view udtf(expression) tableAlias AS columnAlias
    • 解释:用于和split,explode等udtf函数一起使用,能够将一行数据拆分成多行数据,在此基础上可以对拆分的数据进行聚合。

窗口函数

  • over():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化
  • current row:当前行
    • over(partition by name order by orderdate rows between
      UNBOUNDED PRECEDING and current row )
  • n preceding:往前n行数据
  • n following:往后n行数据
  • unbounded:起点。unbounded preceding表示从前面的起点;unbounded following表示到后面的终点
  • lag(col,n):往前第n行数据
  • lead(col,n):往后第n行数据
  • rank:
    • rank()排序相同时会重复,总数不会变(1,1,1,4)
    • dense_rank():排序相同时会重复,总数会减少(1,1,1,2)
    • row_number():根据顺序计算(1,2,3,4)#无论重复还是不重复

自定义函数

  • udf函数:一进一出
  • udaf函数:聚集函数,多进一出
  • udtf函数:一进多出
  • 编程步骤:
    • 继承org.apche.hadoop.hive.ql.UDF
    • 实现evaluate函数:evaluate函数支持重载
    • 在hive的命令行中创建函数
      • 添加jar:add jar linux_jar_path
      • 创建function:create function db.function_name AS class_name;
  • 注意事项:udf必须要有返回类型,可以返回null,但是返回类型不能为void;

自定义udf函数

  • 继承UDF类,重写evaluate方法即可完成

自定义udtf函数

  • 继承GenericUDTF类
  • 重写方法
    • initialize方法:
      • 定义输出数据的列名和类型;
    • process方法:
      • 获取原始数据(第一个传入的参数)和获取分隔符(第二个传入的参数)
      • 将原始数据以分隔符进行split
      • 将数组中的元素都写出:forward(元素)
    • close:回收资源,收尾工作

文件格式

  • TEXTFILE 和 SEQUENCEFILE 的存储格式都是基于行存储的
  • ORC 和 PARQUET 是基于列式存储的。
  • parquet文件包括文件的数据和元数据,因此parquet是自解析的

hive调优

  1. fetch抓取
    1. hive中对某些情况的查询可以不必使用MapReduce计算。例如select * from employees;在这种情况下,hive可以简单的读取表对应的存储目录下的文件,然后输出查询结果到控制台
    2. 设置fetch抓取参数为more。(现在默认是more了,旧版本的是默认minimal)
    3. 设置参数位more后,在全局查找,字段查找、limit查找等都不走MapReduce了!
  2. 本地模式
    1. 大多数hadoop job是需要hadoop提供的完整的可扩展性来处理大数据集。
    2. 但是,hive的输入量是非常小的情况下。为查询执行任务消耗的时间可能会比实际job的执行时间要多得多。这种情况下,可以通过本地模式在单台机器上处理所有的任务。对于小数据集,执行时间可以明显的被缩短
    3. 设置参数开启本地模式为true;
  3. 表的优化
    • 小表、大表join
      1. 将key相对分散,并且数据量小的表放在join左边,能够减少内存溢出错误发生的几率;在进一步,使用map join让小的维度表先进内存,在map端完成reducer。
      2. 现在的版本,小表join大表和大表join小表都进行了优化,现在没有什么变化了。
    • 大表join大表
      1. 空key过滤
        • join超时是因为某些key对应的数据过多,而相同的key对应的数据都会发送到相同的reducer上,从而导致内存不够
        • 分析这些异常的key,如果对应的数据是异常数据,我们可以选择过滤掉这些数据
      2. 空key转换
        • 某些key为空对应的数据很多,但是相应的数据都不是异常数据,必须要包含在join的结果中。
        • 解决:为空key的字段赋一个随机值,使得数据均匀的分到不同的reducer上。
    • mapjoin
      • 如果不指定mapjoin或者不符合mapjoin的条件,join会reduce阶段完成join。这就会容易产生数据倾斜。可以用mapjoin把小表全部加装到map端进行join,避免reducer处理
      • 步骤:
        • 共有两个task。
        • 第一个task是本地task,在客户端本地执行的task,负责扫描小表的数据,并将其转换为hashtable的数据结构,并写入本地的文件中。之后将文件加载到distributecache中
        • 第二个task是一个没有reducetask的MapReduce,启动maptask扫描大表,在map阶段,根据大表的每一条记录去和distributecache中小表对应的hashtable关联,并直接输出结果
  4. groupby:负载均衡(预聚合)
    • map阶段同一个key数据分发到一个reduce,当一个key数据过大时就容易导致数据倾斜了。
    • 并不是所有的操作都是需要在reduce端完成的,很多聚合操作可以在map端进行部分聚合,最后在reduce端得出最终结果(预聚合)
    • 步骤:
      • 产生两个mr job:
        • 第一个mr job中,map的输出结果会随机分配到reduce中,每个reduce中做部分聚合操作,并输出结果。结果:相同的groupByKey有可能会被发送到不同的reduce中,从而起到负载均衡的目的;
        • 第二个mr job中,根据上一个mr的数据结果,按照groupByKey分布到reduce中,完成最终的聚合操作。结果:保证相同的groupByKey被分布到同一个reduce中。
  5. count distinct使用先groupBy再count的方式替换
  6. 避免笛卡尔积
    • 避免join不加on条件,或者是无效的on条件
  7. 行列过滤
    • 列过滤:尽量避免写select * from employees;你需要什么列你就写出来,不能习惯性的用*
    • 行过滤:先进行where过滤出正确的行记录,然后再进行join。
  8. 动态分区调整
    • 设置动态分区,hive会根据分区字段的数据来进行分区。而平时我们用的是静态分区,即需要我们手动指定加载到哪个分区才行。
  9. 分区
  10. mr优化
    1. 合理设置map数
      1. map数决定因素:目录下的文件总个数,input的文件大小、集群设置的文件块大小
      2. 过多的map数会造成资源浪费
    2. 小文件合并
      1. 使用combineHiveInputFormat,具有对小文件进行合并的功能
      2. 默认的hiveinputformat没有对小文件合并的功能
    3. 复杂文件增加map数
      1. 当input的文件很多,任务逻辑很复杂的情况下,可以考虑增加map数来使每个map处理的数据量减少,从而提供任务的执行效率
      2. computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
    4. 合理设置reduce数
      1. 过多的启动和初始化reduce也会消耗时间和资源
      2. 过多的reduce会产生过多 文件,如果文件小就变成了小文件问题了。如果这些文件作为下一个任务的输入,就出现小文件问题了
      3. 考虑原则:
        1. 处理大数据量利用合适的reduce数
        2. 使用单个reduce任务处理数据量大小要合适
  11. 并行执行:
    1. hive查询转化成一个或多个阶段。例如MapReduce阶段、抽样阶段、合并阶段、limit阶段。默认情况下,hive一次只会执行一个阶段。不过,某个特定的job可能包含众多的阶段,而这些阶段并发是完全互相依赖的,也就是说有些阶段是可以并行执行的
    2. job中的并行阶段增多,那么集群利用率就会增加(首先得要有过多的空闲资源)
  12. 严格模式:防止用户执行不好的影响的查询
    1. 例如:hive分区表不带where分区值、直接order而不用limit、使用笛卡尔积
  13. jvm重用:小文件或者task特别多的场景。
    1. jvm的启动过程会有很大的开销。jvm重用即jvm实例在同一个job中重用N次。
    2. 缺点:开启jvm重用将一直占用使用到的task插槽,以便进行重用,直到任务完成后才释放。那么如果某个不平衡的job中有某几个reducetask执行的时间要比其他reducetask消耗的时间多的多的话,那么保留的插槽就会一直空闲着却无法被其他的job使用,知道所有的task都结束了才会释放
  14. 推测执行
    1. 为拖后腿的任务分配一个新的任务(相同)#处理的数据和原始人物相同。谁先完成取谁的结果
    2. 对偏差非常敏感的任务,不建议使用推测执行
  15. 压缩
  16. 执行计划explain

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值