数据堆栈入门(hive篇未完结)

打印 上一主题 下一主题

主题 639|帖子 639|积分 1917

前言:快秋招了,准备学一点数据堆栈的东西,应聘大数据开辟。看课随记。(这里主要是看一点hive的东西,感觉数仓项目用到最多的就是hive)
一、Hive相关

1.Hive是什么?



  • hive是创建在hadoop之上的开源的数据堆栈系统,可以将存储在hadoop的hdfs上的结构化,半结构化的数据文件映射(映射指文件和表之间的对应关系)为一张数据库表,基于表提供了一种雷同于sql的语言:hql,用于访问和分析存储在hadoop文件中的大型数据集.
  • Hive的核心是将hql转化成mapreduce程序,然后将程序提交到hadoop集群执行.
总结来说:Hive负担的功能职责就是将用户编写的hql语言转化为napreduce程序,处理位于HDFS上的数据.
    1.1 既然Hive是一个数据堆栈系统,那它具备数仓的本领嘛?

从功能来讲,数据堆栈软件至少要具备两种本领:存储数据和分析数据的额本领.
Hive固然也具备上述两种本领,但不是本身实现,而是借助hadoop:利用hdfs存储,利用mapreduce查询分析数据.
2.Hive的架构,组件有哪些?



  • 用户接口:Hive提供用户接口写sql.
  • 元数据存储:Hive的元数据存储组件存储的是HDFS中的数据文件与表的映射关系,包括表的数据所在的目录,表的名字,表对应那个文件,表的列,以及表的字段分割符号,表的属性(是否为外部表)等.通常存储在关系型数据库中,如许后续hive才知道写的hql是什么意思.
  • Dirver驱动程序,包括语法剖析器,编译器,优化器,执行器:对hql进行转化.
  • 执行引擎:hive本身不直接处理数据文件,而是通过引擎取处理.Hive3.0支持:MapReduce,Tez,Spark 3种引擎.
3.Hive与数据库

Hive是不是数据库? 不是,Hive是数据堆栈
Hive与数据库的相似之处? Hive的数据模子雷同于RDBMS库表结构,此外还有本身特有的模子.
Hive种的数据可以在粒度级别上分为三类:


  • Table 表
  • Partition 分区
  • Bucket 分桶

4.Hive相关:



  • Hive作为一个数据堆栈,在结构上和传统的数据库看齐,也分为数据库,每一个数据库有各自的表组成.默认数据库default.
  • Hive的数据都是存储在HDFS上的,默认有一个根目录,在hive-site.xml中,由参数hive.metastore.warehouse.dir指定.默认值为/user/hive/warehouse.
      hive数堆栈本质上在hdfs上是一个文件夹                                                                              


  • Hive中的数据库在HDFS上的存储路径为: ${hive.metastore.warehouse.dir}/ databasename.db
  • 比如,名为itcast的数据库存储路径为"/user/hive/warehouse/itcast.db
        4.1 Table 表:



  • Hive表与关系型数据库中的表雷同.Hive中表所对应的数据通常是存储在HDFS中,而表相关的元数据是存储在RDBMS中.
  • Hive中表的数据在HDFS上的路径为{hive.metastore.warehouse.dir}/ databasename.db / tablename.

         4.2 Partitions 分区

Partitions 分区是hive的一种优化本领表.分区是指根据分区列(比方"日期day")的值将表分别为不同分区.如许可以更快的对指定分区数据进行查询.


  • 分区在存储层面上的表现是:table表目录下以子文件夹形式存在.
  • 一个文件夹表现一个分区.子文件命名标准:分区列=分区值.

        4.3 Bucket 分桶

bucket分桶表是hive的一种优化本领表.分桶是指根据表中字段(比方"编号ID")的值,经过hash计算规则将数据文件分别成指定的若干个小文件.
分桶规则:hashfunc(字段)%桶个数,玉树雷同的分到同一个文件.

分桶好处:优化join查询和方便抽样查询.
分桶在HDFS中表现为同一个表目录根据hash散列之后变成多个文件.

5.在Hive中,什么是元数据?

元数据(metadata),是描述数据的数据,主要是描述数据的属性的信息,比如:存储位置,历史数据,资源查找,文件记录等.

 Hive Metadata:



  • hive的元数据
  • 包罗用hive创建的database,table,表的位置,类型,属性,字段次序等元信息.
  • 元数据存储在关系型数据库中,如hive内置的Derby,大概第三方如Mysql.
 Hive Metastore:

二、Hive的语法

1.创建表与删除表

1.1、创建表的根本语法

  1. create [external] Table table_name
  2. [(col_name data_type [comment col_comment],..)]
  3. [comment table_comment]
  4. [PARTITIONED BY (col_name data_type [comment col_comment],..)]
  5. [CLUSTERED BY (col_name,col_name,....)]
  6. [STORTED BY (col_name [ASC|DESC],...)] INTO num_buckets BUCKETS]
  7. [ROW FORMAT row_format]
  8. [STORT AS FILE_FORMAT]
  9. [LOCATION hdfs_path]
复制代码


  • extrenal 外部表
  • partitioned by 分区表
  • clustered by 分桶表
  • stored as 存储格式
  • location 存储位置
1.2删除表的语法

  1. drop table db_name.table_name
复制代码
2.在Hive中,可以创建的表的类型。



  • 内部表
  • 外部表
  • 分区表
  • 分桶表
2.1 内部表

  1. create table tb_name
复制代码
未被external修饰的表就是内部表。
内部表的位置由hive.metastore.warehouse.dir参数决定(默认:/user/hive/warehouse.)
删除内部表会直接删除元数据(metastore)及存储数据
2.2 外部表

  1. create external table tb_name ... LOCATION "HDFS_path"
复制代码
外部表被external修饰,其数据可以在任何位置,通过LOCATION关键字指定。
数据存储的不同也代表了这个表在理念上并不是hive在管理,而是可以随意临时链接在外部数据上。
以是在删除外部表,仅仅删除元数据,不删除数据本身。
(注意,表本身和数据是相互独立的,可以先有表,然后把数据移动到表指定的location中,也可以先有数据,然后创建表通过location指向数据。)
2.3 Hive数据加载和导出

        数据的加载:(从其他地方加载到hive,两种方法)


  • 利用LOAD语法,从外部将数据加载到HIVE内。(从文件加载)
(hive的数据存储在hdfs的路径上,因为hdfs是分布式存储系统,然后在从hdfs上加载到hive内)
  1. LOAD DATA [LOCAL] INPATH "filepath" [OVERWRITE] INTO TABLE tb_name
复制代码

  • 数据假如在HDFS上,不必要local关键字,假如在linux本地,必要local关键字。
  • ”file path“ 数据路径
  • overwrite :利用表现覆盖,不利用表现追加。
  • load方式导入数据,不会走mapreduce,小文件加载速度快,大文件加载和mapreduce速度没啥区别。
 --->从创建表到将数据load到hive内(指在hive内创建表,然后把其他地方的数据加载到hive中)
  1. # 建表(内部表默认在user/hive/
  2. create table myhive.test_load(
  3. dt string comment "时间",
  4. user_id string comment "用户id",
  5. search_word string comment "搜索关键词",
  6. url string comment "网址" )
  7. row format delimited fields terminated by "\t";
  8. # 数据加载(现在是有表,然后将数据加载到表里边,即hive内,即hdfs的一块区域,但是这个区域是hive)
  9. 1.将linux系统的数据上传。
  10. load data [local] inpath "/home/user/search_log.txt' into table myhive.test_load;
  11. 2.使用hdfs命令先将数据上传到hdfs系统中,再从hdfs系统上传。
  12. hdfs -s -put search_log.txt /tmp  # 将本地路径为search_log.txt的文件上传到hdfs下的tmp上。
  13. (该句在linux上执行)
  14. load data inpath "/tmp/search_log.txt" into table myhive.test_load;
复制代码
注意:将本地的数据上传,本地数据还在,将hdfs的数据上传,hdfs的数据没有了,相当于移动。 


  • 通过SQL语句加载 ,从其他表加载数据。
情景:如今hive下边有两张表,一张table1,一张table2,如今table1中有数据,table2是空的,如今要从table1中加载数据到table2中:
语法:
  1. INSERT [OVERWRITE | INTO ] TABLE table_name
  2. [PARTITION (partcol1=val1,partcol2=val2..) [if not exists] ]
  3. select_statement1 FROM from_statement
  4. # 将select查询语句的结果插入到其他表中,被select查询的表可以是内部表也可以是外部表
复制代码
举例:
  1. insert into table2 select * from table1
  2. insert overwrite tabel2 select  * from table1
复制代码
        数据的导出(将hive表中的数据导出到其他恣意目录,比方linux本地的磁盘,大概hdfs,mysql等。)
语法:
  1. # 将数据导出到linux上需要local关键字,将数据导出到hdfs不需要关键字。
  2. insert overwrite [local] directory "path"
  3. select_statement1 from from_statement;
复制代码
举例:
将table1中的数据导出到linux下或hdfs。
  1. # 将查询结果导出到本地,使用默认列分隔符
  2. insert overwrite loacl directory "/home/hadoop/export1"
  3. select * from table1
  4. # 将查询结果导出到本地,使用指定列分隔符
  5. insert overwrite local directory "/home/hadoop/export2"
  6. row format delimited fields terminated by "\t"
  7. select * from table1
  8. # 将查询结果导出到hdfs上。
  9. insert overwrite directory "/tmp/export"
  10. row format delimited fields terminated by "\t"
  11. select * from table1
复制代码
数据的导入导出总结:
1.不管时导入和导出,带local表现从本地导入大概导出到本地,不带表现从hdfs导入,大概导出到hdfs。
2.利用insert会走mapreduce,用时比力长。(但是当文件很大时无所谓,mapreduce和其他的方式速度差不多)
2.4  分区表

2.4.1 分区表的概念

        把大的数据,按照每天大概每小时进行切分,切分成一个个小的文件,分区表就是在表文件夹下,创建子文件夹,把对应数据存放在子文件夹里边,同样,分区之后还可能有分区,那就是再创建文件夹。

        如上图所示,我们知道,hive的内部表实在是hdfs上的一个文件夹,默认路径是“/user/hive/warehouse/database_name.db/table_name ”,那么表的分区是在表的文件夹,又放了子文件夹,来存放数据。即:数据库,表,表分区1,表分区2...表分区N 都是文件夹。在对应的分区文件夹里添加了分区数据。如许做的好处是每个分区是独立的文件夹,那么要对某个时间做处理,只必要对该子文件夹做处理。
2.4.2  创建分区表语法

下边提到的创建分区表的逻辑是先创建表,然后将数据加载到表对应的分区中。
语法
  1. create table tabel_name partition by (分区列 列类型...)
  2. row format delimited fields terminated by '';
复制代码
举例:
  1. # 创建分区表语法
  2. create table score (s_id string,
  3.                     c_id string,
  4.                     s_score int)
  5. partition by (month string)
  6. row format delimited fields terminated by "\t";
  7. # 创建一个表带多个分区,分区的层次是年月日。三者是上下级,不是平级。
  8. create table score (s_id string,
  9.                     c_id string,
  10.                     s_score int)
  11. partition by (year string,
  12.               month string,
  13.               day string)
  14. row format delimited fields terminated by "\t";
  15. # 加载数据到分区表中
  16. load data inpath "/export/server/hivedatas/score.txt"
  17. into table score
  18. partition (month="202006")
  19. # 加载数据到一个表的多个分区中
  20. load data inpath "/export/server/hivedatas/score.txt"
  21. into table score
  22. partition (year="2020",month="06",day="01")
复制代码


  • 创建了分区之后,在查看表中数据的时候,会多出一个额外的列,这个列是分区的列,如下表,多了一个month列。(一个分区)



  • 多个分区: 

分区表注意: 


  • 在创建分区表时,创建了几个分区,插入数据的时候就要插入几个分区的数据。
2.5 分桶表 

2.5.1 分桶表的概念

分桶表和分区表一样,也是通过改变表的存储形式,从而完成对表优化的一种调优方式。
 分桶表和分布表的不同点是,分区是将表拆分到不同的子文件夹中进行存储,分桶是将表拆分到固定数目的不同文件中进行存储。
 注意:分区是文件夹级别,分桶是文件级别。
2.5.2 分桶表的创建

语法:
  1. # 首先开启分桶的自动优化(自动匹配reduce task数量和桶的数量一致)
  2. set hive.enforce.bucketing=true;
  3. # 创建分桶表
  4. create table 表名(列名1 列类型1,列名2 列类型2,..)
  5. clustered by (列名)
  6. into num buckets
  7. row format delimited fields terminated by "\t";
复制代码
2.5.3 分桶表数据的加载

如今已经创建好表了,往分桶表里加载数据,前边已经学了往分区表中加载数据,有两种方法。
但是对于分桶表来说,只可以用insert into/overwrite方法。(该方法必须时从一张表中加载数据到另一张表)
以是往分桶表中添加数据时,先创建一个临时表1,用load data的方法将数据先加载到临时表1中,然后再从临时表1导入到分桶表中。
  1. # 创建普通表
  2. # 该普通表不用分区或分桶,但是列分割符要和分桶表的列分割符一样
  3. create table 临时表名 (c_id string,c_name string,t_id string)
  4. row format delimited fields terminated by "\t";
  5. # 把数据加载到普通表中
  6. load data local
  7. inpath "/export/sever/hivedatas/course.txt"
  8. into table 临时表名
  9. # 构建分桶表
  10. create table table1(c_id string,c_name string,t_id string)
  11. clustered by (c_id)
  12. into 3 buckets
  13. row format delimited fields terminated by "\t";
  14. # 把数据从临时表加载到分桶表
  15. insert overwrite 分桶表  select * from 临时表 cluster by (c_id)
复制代码


  •   为什么不可以用load data的方法加载数据到分桶表中?
因为假如没有分桶,只分区的话,那就是数据放到指定的文件夹,但是有分桶的话,已经指定文件的数目了,有分区:每个分区n个文件,没有分区,统共有n个文件,这种情况下数据必须一分为n,那数据该怎么插入呢?
当把数据分为n份的时候,并不是随机的将数据分成n份,而是基于分桶列的值进行hash取模来决定数据该分到那个文件。load data方式加载数据不会走mapreduce,没有计算,而分桶必要计算,以是不能用load data。


  • 什么是基于分桶列的值进行hash取模?
Hash算法是一种加密算法,对于同样的值,加密之后的结果是一样的,比如说字符串"abcde"加密之后是12345,那么对该12345取模(分为几个桶就对谁取模),如许,按照取模的余数来分别数据的文件。
        上边对c_id列进行分桶,那么比如c_id的一个值是“aa",经过hash加密是56,如今要分成3桶,那么取模之后的余数是2,那么他就被分到2的文件夹。以是,同一个值肯定在一个文件。


  •  为什么分桶表可以提升性能?
1.单值过滤:我们知道份几个同,假如想过滤某一个值,就在计算一下他的hash取余,如许一下就可以定位到在那个桶。
2.双表join:可以知道对应的桶里的内容,那么join的时候只必要join该桶就行,可以减少不必要的数据交互。
3.可以基于分桶列,来group by分组:因为雷同的值就在一个桶,以是可以在分桶列上进行分组。
3.修改表操作

  1. # 修改表名字(sql也适用)
  2. alter table table1 rename to table2;
  3. # 修改表的属性(sql不适用)
  4. --首先查看表的属性
  5. desc formatted 表名;
  6. --将表改为外部表
  7. alter table 表名 SET tbpropertites('external'='true')
  8. --修改表的comment,comment是建表时候的注释
  9. alter table 表名 SET tbpropertites('comment'='this is new')
  10. # 添加分区
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

耶耶耶耶耶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表