hadoop离线day09--Apache Hive

hadoop离线day09--Apache Hive

目录

hadoop离线day09--Apache Hive

今日内容大纲

1、HQL DDL 数据定义语言

分区表

分区表创建

分区表加载数据

总结及注意事项

多重分区表

分桶表

分桶表创建

分桶表加载数据

HQL DDL 数据定义语言

修改表

show场景语法

2、HQL DML 数据操纵语言

Dynamic partition inserts 动态分区插入

导出数据操作

3、HQL DQL 数据查询语言

Common Table Expressions(CTE)

Hive join

4、Hive shell命令行 参数配置



今日内容大纲

#1、HQL DDL 数据定义语言
    创建表
        分区表
        分桶表
    修改表 alter
    常用的show命令
 #2、HQL DML 数据操纵语言
    load加载数据
    insert插入数据
        mysql:insert+values
        hive:insert+select
        动态分区插入
        数据导出
 #3、HQL DQL 数据查询语言
    select
        hive自己特有的查询
        CTE语法
        union语法
     Hive join
        inner join、left join
 #4、Hive shell命令行 参数配置
    bin/hive shell
    bin/beeline jdbc
    hive参数配置方式

1、HQL DDL 数据定义语言

  • 分区表

    • 分区表引入,产生背景

      --创建一张表 映射一个文件
      create table t_user(id int,name string,country string) row format delimited fields terminated by ',';
      ​
      --能否在一张表的目录下 映射多个文件呢?
      --可以 保证多个文件之间字段、类型、个数、顺序是一致
      ​
      --查询:找出来自于中国的用户
      select * from t_user where country ="china";
      --问题:在where过滤的时候 需要进行全表扫描 判断过滤条件十分满足
      --全表扫描性能不高 如何优化?
      ​
      --通过hdfs底层存储格式  猜想:能否基于文件去扫描指定的文件,而不是全表扫描 效率不就提高了吗?
    • 分区表创建

      --基于业务分析 决定根据国家分区
      create table t_user_part(id int,name string,country string) partitioned by(country string) row format delimited fields terminated by ',';
      ​
      Error: Error while compiling statement: FAILED: SemanticException [Error 10035]: Column repeated in partitioning columns
      --建表报错 分区字段重复
      ​
      create table t_user_part(id int,name string,country string) partitioned by(guojia string) row format delimited fields terminated by ',';
      ​
    • 分区表加载数据

      --猜想方式1:使用hadoop fs -put 上传表的目录下
       失败 没有指定该文件属于哪个分区  没有指定分区值
       
      --正确方式: load data语法
      load data local inpath '/root/hivedata/chian.txt' into table t_user_part partition(guojia="zhongguo");
      --加载china.txt文件到分区表中 并且指定该文件属于zhongguo分区。
      ​
      load data local inpath '/root/hivedata/usa.txt' into table t_user_part partition(guojia="meiguo");
      load data local inpath '/root/hivedata/japan.txt' into table t_user_part partition(guojia="riben");
    • 分区表使用

      --查询:找出来自于中国的用户
      select * from t_user where country ="china"; --非分区字段查询
      ​
      select * from t_user where guojia ="zhongguo"; --基于分区表分区字段查询
    • 总结及注意事项

      • 分区表是一种优化表,主要是提高查询效率,减少全表扫描。

      • 分区的字段不能是表中已有的字段?为什么 分区字段也会作为结果显示查询内容上,不能重复。

      • 分区字段是虚拟的字段,其内容不是来自于底层文件的映射,来自于加载数据时指定。

      • 分区表底层形式就是在表的文件夹下面继续创建子文件,子文件的名字就是分区字段和分区值组合

        #非分区表
        /user/hive/warehouse/itcast.db/t_user
                                            china.txt
                                            japan.txt
                                            usa.txt
        #分区表                                    
        /user/hive/warehouse/itcast.db/t_user_part
                                                /guojia=zhongguo
                                                            china.txt
                                                /guojia=riben
                                                            japan.txt
                                                /guojia=meiguo
                                                            usa.txt
      • 企业中常见的分区字段

        • 时间维度 年 月 天

        • 地域维度 省 市

    • 多重分区表

      • Hive支持在多个分区字段,也就是所谓多重分区表,常见的是2分区表。

      • 多分区的意思是指在前一个分区的基础上继续分区

      • 底层来看就是文件夹下面继续创建子文件

      --创建2分区表
      create table t_user_double_part(id int,name string,country string) partitioned by(guojia string,sheng string) row format delimited fields terminated by ',';
      ​
      --load
      load data local inpath '/root/hivedata/china_sh.txt' into table t_user_double_part partition(guojia="zhongguo",sheng="shanghai");
      ​
      load data local inpath '/root/hivedata/china_bj.txt' into table t_user_double_part partition(guojia="zhongguo",sheng="beijing");
      ​
      load data local inpath '/root/hivedata/usa_dz.txt' into table t_user_double_part partition(guojia="meiguo",sheng="dezhou");
      ​
      --查询
      select * from t_user_double_part where guojia ="zhongguo";
      ​
      select * from t_user_double_part where guojia ="zhongguo" and sheng ="shanghai";
  • 分桶表

    • 语法上剖析

      [clustered by (col_name, col_name, ...)
      [sorted by (col_name [asc|desc], ...)] into num_buckets buckets]
      ​
      --精简
      clustered by xxx into N buckets
      ​
      clustered by xxx  根据xxx分在一起
      into N buckets  分为几桶
      ​
      --通俗解释:根据xxx字段把表的数据分为N个部分。
      t_user(id,name,country)
      ​
      根据谁分?  clustered by xxx   xxx就是分的字段
      ​
      分为几个部分?into N buckets   N
      ​
      如何分?
          --如果分桶的字段xxx是数值类型字段,     xxx  % N        余数相同的到一起
          --如果分桶的字段xxx是字符串或者其他类型  xxx.hash  % N   余数相同的到一起
          
      --如果有需求 还可以知道每个分桶内排序规则
      sorted by (col_name [asc|desc])
    • 分桶表创建

      create table stu_buck(Sno int,Sname string,Sex string,Sage int,Sdept string)
      clustered by(Sno) 
      into 4 buckets
      row format delimited
      fields terminated by ',';
    • 分桶表加载数据

      --如何判断分桶表的数据加载成功
          1、正确解析显示数据
          2、底层文件分成N个部分
          
      --直接hadoop fs-put  和load加载都是不可以的
      --分桶表采用insert+select 间接的方式才能加载数据
      ​
      --step1:创建一个普通的表 并加载数据到普通表中
      create table student(Sno int,Sname string,Sex string,Sage int,Sdept string)
      row format delimited
      fields terminated by ',';
      ​
      --step2: 开启分桶功能
      set hive.enforce.bucketing = true;
      ​
      --注意这个参数 hive.enforce.bucketing
          Default Value: 
          Hive 0.x: false
          Hive 1.x: false
          Hive 2.x: removed, which effectively makes it always true (HIVE-12331)
          Added In: Hive 0.6.0
         
      --step3: 把数据从普通表中查询出来插入到分桶表中
      ​
      insert into table stu_buck
      select * from student;
    • 分桶表使用

      • 和正常表一样使用,底层查询时hive自动优化。

    • 分桶表总结及注意事项

      • 分桶表也是一种优化手段表,主要提高join查询时候效率,减少笛卡尔积数量;

      • 此外还可以方便抽样查询。

      • 分桶表的字段必须是表中已有字段。

      • hadoop离线day09--Apache Hive_第1张图片


HQL DDL 数据定义语言

  • 修改表

    • 修改表的属性信息

    • 修改表的分区属性信息

    • 修改表的字段

  • 语法核心关键字:alter

  • 注意:在Hive中,修改表的操作使用不多,可以使用drop+create 替代。为什么?

    #mysql中不这么干?
    create table--->insert values  #意味着mysql加载数据的成本极高。
    ​
    #hive中为什么可以?
    create table--->映射已经存在的文件(外部表保护文件) # 删除再创建的成本极低 
  • 栗子

    --增加分区  先有分区文件  补充元数据
    ALTER TABLE t_user_part ADD PARTITION (guojia='yingguo') location
    '/user/hive/warehouse/itcast.db/t_user_part/guojia=yingguo';
    ​
    --删除分区
    ALTER TABLE t_user_part DROP IF EXISTS PARTITION (guojia='yingguo');
    ​
    --修改分区 重命名分区
    ALTER TABLE t_user_part PARTITION (guojia='yingguo') RENAME TO PARTITION (guojia='dydg');
    ​
    --列操作
    ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name STRING);
        --注:ADD 是代表新增一个字段,新增字段位置在所有列后面(partition 列前)
        --REPLACE 则是表示替换表中所有字段。
        
    ALTER TABLE table_name RENAME TO new_table_name 

show场景语法

--1、显示所有数据库 SCHEMAS和DATABASES的用法 功能一样
show databases;
show schemas;
​
--2、显示当前数据库所有表
show tables;
SHOW TABLES [IN database_name]; --指定某个数据库
​
--3、显示表分区信息,分区按字母顺序列出,不是分区表执行该语句会报错
show partitions table_name;
​
​
--4、显示表/分区的扩展信息
SHOW TABLE EXTENDED [IN|FROM database_name] LIKE table_name;
show table extended like student;
describe formatted itheima.student;
​
--5、显示表的属性信息
show tblproperties student;
​
--6、显示表建表语句
show create table student;
​
--9、显示表中的所有列,包括分区列。
SHOW COLUMNS (FROM|IN) table_name [(FROM|IN) db_name];
show columns  in student;
​
--10、显示当前支持的所有自定义和内置的函数
show functions;
​
--11、Describe desc
--查看表信息
desc extended table_name;
--查看表信息(格式化美观)
desc formatted table_name;
--查看数据库相关信息
describe database database_name;
#探究
    1、hive做了什么
        将结构化文件映射成为一张表 记录着映射信息(元数据)
    2、MySQL中存储的是什么数据
        存储着映射信息 元数据
    3、HDFS中存储的是什么数据
        存储的是结构化文件  表的真实的数据
​
#查看表的元数据信息 hive记录了这个表哪些信息
desc formatted student;

2、HQL DML 数据操纵语言

  • load

    • 功能:加载操作是将数据文件移动到与 Hive表对应的位置的纯复制/移动操作。

    • 语法

      LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO
      TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
    • 核心关键字--local

      • 有local 表示从本地文件系统加载到hive表中

      • 没有local 表示从hdfs文件系统加载到hive表中

    • 究竟哪个本地是本地文件系统。

    • 栗子

      create table student_from_local(Sno int,Sname string,Sex string,Sage int,Sdept string)
      row format delimited
      fields terminated by ',';
      ​
      create table student_from_hdfs(Sno int,Sname string,Sex string,Sage int,Sdept string)
      row format delimited
      fields terminated by ',';
      ​
      --1、从本地加载数据到student_from_local
      load data local inpath '/root/hivedata/students.txt' into table student_from_local;
          --从本地加载的时候 是一个数据复制操作 
          --底层的本质就是 hadoop fs -put 
          
      --2、从HDFS加载数据到student_from_hdfs
      load data  inpath '/stu/students.txt' into table student_from_hdfs;
          --从hdfs加载的时候 是一个数据移动操作 
          --底层的本质就是 hadoop fs -mv 
    • 结论:官方推荐使用load命令加载数据到Hive表中。实际上无论什么方式,只有把文件放置在表的目录下就可以。

    • hadoop离线day09--Apache Hive_第2张图片
  • insert插入数据

    • 回顾

      mysql: insert into table values(1,"zhangsan");
      ​
      --insert +values语法在hive中能否使用。
      ​
      create table t_insert(id int,name string);
      ​
      insert into table t_insert values(1,"allen");
      ​
      --语法可以在hive使用 但是效率较低。 推荐使用load加载数据方式。
    • insert在hive中如何

      • 语法:insert+select

      • 功能:把后面查询返回的结果作为内容插入到表中 也是ETL中常见的操作。

      • 注意:查询返回结果的字段类型、顺序、含义、个数要和待插入表一致。

      • 栗子

        create table t_insert_1(name string);
        ​
        insert into t_insert_1 select name from t_insert;
        ​
        --如何插入的表是分区表 还需要指定分区值
        insert into t_insert_1 partition() select name from t_insert;
    •  开启智能本地模式

      SET hive.exec.mode.local.auto=true;
    • Multi Inserts 多重插入 多次插入

      • 一次扫描,多次插入 减少全表扫描的次数

      from source_table                     
      insert overwrite table test_insert1 
      select id
      insert overwrite table test_insert2
      select name;
    • Dynamic partition inserts 动态分区插入

      • 探讨

        --动态分区、静态分区
        --研究的是:分区表的分区值是如何决定的?
        ​
        load data local inpath '/root/hivedata/usa.txt' into table t_user_part partition(guojia="meiguo");
        ​
        usa.txt--->meiguo  --sql中写死的  静态分区
        insert +seletc     --根据查询结果动态确定的分区  动态分区
      • hadoop离线day09--Apache Hive_第3张图片
      • 栗子

        --step1: 开启动态分区功能 设定动态分区的执行模式
        set hive.exec.dynamic.partition=true;    #是否开启动态分区功能,默认false关闭。
        set hive.exec.dynamic.partition.mode=nonstrict;   #动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。
        ​
        Error: Error while compiling statement: FAILED: SemanticException [Error 10096]: Dynamic partition strict mode requires at least one static partition column. To turn this off set hive.exec.dynamic.partition.mode=nonstrict (state=42000,code=10096)
        ​
        --理解严格 非严格模式
        insert into table d_p_t partition(month="2015-05",day)
        select ip,day from dynamic_partition_table;  --严格模式
        ​
        insert into table d_p_t partition(month,day)  --非严格模式
        select ip,month,day from dynamic_partition_table;
        ​
        ​
        --step2:执行动态分区
        insert overwrite table d_p_t partition (month,day) 
        select ip,substr(day,1,7) as month,day from dynamic_partition_table;
    • 导出数据操作

      • 语法

        INSERT OVERWRITE [LOCAL] DIRECTORY directory1 SELECT ... FROM ...;
      • 注意事项

        • local表示把数据导出到HS2所在机器的本地文件系统 否则就导出到HDFS.

        • OVERWRITE表示把目录下的数据给覆盖。

        • 默认导出的数据以\001作为字段分隔符 也可以指定分隔符。

      • 栗子

        INSERT OVERWRITE LOCAL DIRECTORY '/tmp/aaa' SELECT * FROM student;
        ​
        INSERT OVERWRITE DIRECTORY '/aaa' SELECT * FROM student;

3、HQL DQL 数据查询语言

  • 完整语法树

    [WITH CommonTableExpression (, CommonTableExpression)*]
    SELECT [ALL | DISTINCT] select_expr, select_expr, ...
      FROM table_reference
      [WHERE where_condition]
      [GROUP BY col_list]
      [ORDER BY col_list]
      [CLUSTER BY col_list
        | [DISTRIBUTE BY col_list] [SORT BY col_list]
      ]
     [LIMIT [offset,] rows];
  • CLUSTER BY 分桶查询

    • 功能:根据指定的字段把数据分成若干部分,每个部分中再根据这个字段进行排序,只能正序

    • 概况:根据字段 分且排序动作。

    0: jdbc:hive2://node1:10000> select * from student;
    +--------------+----------------+--------------+---------------+----------------+--+
    | student.sno  | student.sname  | student.sex  | student.sage  | student.sdept  |
    +--------------+----------------+--------------+---------------+----------------+--+
    ​
    --1、根据谁分
        CLUSTER BY  xxx
    ​
    --2、分成几个部分
        取决于底层reducetask的个数  个数如何决定的呢?
        如果用户不设置 自己根据数据量大小自动评估
        如果用户手动设置 就以设置的为准
    ​
    --3、如何分
        规则和分桶表的规则一模一样
        
    select * from student cluster by sno;
    ---默认情况下 根据输入数据量来自动评估reducetask个数
    Number of reduce tasks not specified. Estimated from input data size: 1
    ​
    --手动设置reducetask个数
    set mapreduce.job.reduces =2;
    Number of reduce tasks not specified. Defaulting to jobconf value of: 2
    ​
    set mapreduce.job.reduces =3;
    Number of reduce tasks not specified. Defaulting to jobconf value of: 3
    ​
    --需求:根据sno分为2个部分  每个部分中根据sage 倒序排序
    set mapreduce.job.reduces =2;
    select * from student cluster by sno sort by sage desc;
    ​
    Error: Error while compiling statement: FAILED: SemanticException 1:45 Cannot have both CLUSTER BY and SORT BY clauses. Error encountered near token 'sage' (state=42000,code=40000)
  • DISTRIBUTE BY + SORT BY

    • 功能:DISTRIBUTE BY 只负责分 SORT BY只负责排序 两个字段还可以不一样。

    • 如果字段一样的话:CLUSTER BY(分且排序)= DISTRIBUTE BY(分) +SORT BY(排序)

    set mapreduce.job.reduces =2;
    select * from student distribute by sno sort by sage desc;
  • ORDER BY 全局排序

    • 如何理解全局二字? 全局意味着所有的数据都必须在一个文件中,意味着底层只能有一个reducetask.

    • 为了满足order by全局的实现,在编译期间hive会强制将reducetask个数设置为1。

    set mapreduce.job.reduces =4;
    select * from student order by sage desc;
    --在编译期间 hive把个数设置为1 用户设置的不生效
    Number of reduce tasks determined at compile time: 1
    • order by 、sort by

      • sort by是在数据进行完拆分,每个部分内部排序 局部排序

      • order by是全局数据排序 不会对数据拆分 数据在一起的 完整 全局!!!

      • hadoop离线day09--Apache Hive_第4张图片

  • union联合查询

    • 功能:将多个select查询返回的结果集合并为一个结果集。

    • 语法:

      select_statement 
      UNION [ALL | DISTINCT] 
      select_statement 
      UNION [ALL | DISTINCT] 
      select_statement ...;
      ​
      --1、union= union distinct 结果集去重
      --2、union all 结果集不去重
    • 栗子

      select sno,sname from student_from_local
      UNION
      select sno,sname from student_from_hdfs;
      ​
      --和上面一样
      select sno,sname from student_from_local
      UNION DISTINCT
      select sno,sname from student_from_hdfs;
      ​
      --使用ALL关键字会保留重复行。
      select sno,sname from student_from_local
      UNION ALL
      select sno,sname from student_from_hdfs limit 2;
    • 注意事项

      • 如果想针对某一条select结果进行条件控制 使用嵌套子查询包裹;

      • 如果把条件控制写在最后一个select后,对整个union之后的结果集进行操作。

  • Common Table Expressions(CTE)

    • 以with关键字引导的一个子查询 其命令可以在后续的查询中多次使用。

    • 语法糖。

    --select语句中的CTE
    with q1 as (select sno,sname,sage from student where sno = 95002)
    select *
    from q1;
    ​
    --嵌套子查询语法
    select  * from (select sno,sname,sage from student where sno = 95002) as q1;
    ​
    -- from风格
    with q1 as (select sno,sname,sage from student where sno = 95002)
    from q1
    select *;
    ​
    -- chaining CTEs 链式
    with q1 as ( select * from student where sno = 95002),
         q2 as ( select sno,sname,sage from q1)
    select * from (select sno from q2) a;
  • Hive join

    • hadoop离线day09--Apache Hive_第5张图片

    • 产生背景

      #现实中 不会把所有的数据都存储在一张表中 而是根据业务 应用分别存储。
      ​
      #在某些查询的需求中 又需要基于多张表共同查询返回结果 需要join关联查询。
    • 6种join语法

      join_table:
          table_reference [INNER] JOIN table_factor [join_condition]
        | table_reference {LEFT|RIGHT|FULL} [OUTER] JOIN table_reference join_condition
        | table_reference LEFT SEMI JOIN table_reference join_condition
        | table_reference CROSS JOIN table_reference [join_condition] (as of Hive 0.10)
      • inner join

        inner join == join  默认就是内连接
        ​
        --左右两边都满足的返回
      • outer join

        full outer join == outer join  全外连接 外连接
      • left join

        以左表为准,显示左表的所有内容
        右表与之关联 关联上的显示  关联不上的显示null
        
        
        
      • right join

        与left join相反
        
        
        
      • left semi join

        左半开连接 == 效果等于内关联只显示左表的部分
        ​
        select * from a left semi join b on a.id = b.id;
        +-------+---------
        | a.id  | a.name  
        +-------+---------
        | 2     | b       
        | 3     | c       
        | 7     | y       
        +-------+---------
        ​
        ​
        select a.* from a inner join b on a.id=b.id;
        +-------+---------
        | a.id  | a.name  
        +-------+---------
        | 2     | b       
        | 3     | c       
        | 7     | y       
        +-------+---------
      • cross join(#慎用)

        --笛卡尔积join 交叉相差  往往不带on条件
        ​
        --级联求和 级联累加  自己和自己join可以解决
        ​
        --更好的方式  sum + windows function
    • 注意事项

      • Hive 支持等值连接(a.id = b.id),不支持非等值(a.id>b.id)的连接。

        select * from a join b on a.id = b.id;
        ​
        select * from a join b on a.id > b.id; --当下hive 2.1.0不支持。
    • 难点

      • join的优化

        • map端join

        • reduce端join(common join)

        • bucket join

        • 大小表join

        • 大表join 空值处理问题

      • 如何根据业务需求写join语句


4、Hive shell命令行 参数配置

  • shell命令行

    • 位置:bin/hive

    • 功能1:启动hive的相关服务

      /export/server/hive/bin/hive --service hiveserver2|metastore
    • 功能2:作为第一代客户端访问metastore服务

    • 功能3:执行HQL脚本

      #执行后面指定的sql
      /export/server/hive/bin/hive -e 'select sno from itcast.student limit 3'
      ​
      #执行后面指定的sql文件
      vim xxx.sql
      ​
      $HIVE_HOME/bin/hive -f /home/my/hive-script.sql
      $HIVE_HOME/bin/hive -f hdfs://:/hive-script.sql
      ​
      #sql文件后缀名 见名知意  通常以.sql结尾 可以任意后缀名  保证里面内容sql语法正确即可。
  • Hive参数配置及方式

    • 配置参数在哪里

      https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties

    • 如何配置参数

      • 方式1:hive-site.xml中 覆盖default。

        影响的是这个安装包的任何一种使用方式。
        不管是启动服务 还是基于本安装包启动客户端 都会加载该文件。
        
        
        
      • 方式2:--hiveconf

        /export/server/hive/bin/hive --service metastore
        ​
        /export/server/hive/bin/hive --service metastore --hiveconf  hive.root.logger=DEBUG,console
        ​
        影响的服务的生命周期  客户端的生命周期
      • 方式3:使用set命令

        set hive.exec.dynamic.partition=true;    #是否开启动态分区功能,默认false关闭。
        set hive.exec.dynamic.partition.mode=nonstrict;  
        ​
        影响的客户端和服务之间的session会话
        ​
        session结束 设置参数失效  恢复默认值
    • 企业开发中,推荐使用set命令

      谁需要 谁设置 谁生效 影响其他人使用。
      
      
      
    • 优先级:set命令最高

    • Hive作为基于Hadoop的软件 还会把Hadoop的配置文件加载进来 作为自己的配置的一部分。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Java基础,Hadoop)