1、什么是Hive
  hive是基于hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表
  并提供类sql查询功能

2、为什么要用Hive
  1、直接使用hadoop所面临的问题
    人员学习成本太高
    项目周期要求太短
    MapReduce实现复杂查询逻辑开发难度太大

  2、为什么要使用Hive
    操作接口采用类SQL语法,提供快速开发的能力。
    避免了去写MapReduce,减少开发人员的学习成本。
    扩展功能很方便。

  3、Hive的特点:可扩展,延展性,容错

  4、Hive的数据存储
    1、Hive中所有的数据都存储在 HDFS 中,没有专门的数据存储格式(可支持Text,SequenceFile,ParquetFile,RCFILE等)
    2、只需要在创建表的时候告诉 Hive 数据中的列分隔符和行分隔符,Hive 就可以解析数据。
    3、Hive 中包含以下数据模型:DB、Table,External Table,Partition,Bucket。
      # db:在hdfs中表现为${hive.metastore.warehouse.dir}目录下一个文件夹
      # table:在hdfs中表现所属db目录下一个文件夹
      # external table:与table类似,不过其数据存放位置可以在任意指定路径
      # partition:在hdfs中表现为table目录下的子目录
      # bucket:在hdfs中表现为同一个表目录下根据hash散列之后的多个文件

  5、使用方式:
    启动方式,(假如是在hadoop01上):
    启动为前台:bin/hiveserver2
    启动为后台:nohup bin/hiveserver2 1>/var/log/hiveserver.log 2>/var/log/hiveserver.err &
    启动成功后,可以在别的节点上用beeline去连接

    方式(1)
      hive/bin/beeline 回车,进入beeline的命令界面
      输入命令连接hiveserver2
      beeline> !connect jdbc:hive2//mini1:10000
      (hadoop01是hiveserver2所启动的那台主机名,端口默认是10000)
    方式(2)
      或者启动就连接:
      bin/beeline -u jdbc:hive2://mini1:10000 -n hadoop

    执行hive 的sql命令
    [hadoop@hdp-node-02 ~]$ hive -e ‘sql’

 

3、HIVE基本操作
  3.1、DDL操作
    创建表
      建表语句
        CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
          [(col_name data_type [COMMENT col_comment], ...)]
          [COMMENT table_comment]
          [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
          [CLUSTERED BY (col_name, col_name, ...)
          [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
          [ROW FORMAT row_format]
          [STORED AS file_format]
          [LOCATION hdfs_path]
    说明:
      1、 CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;
        用户可以用 IF NOT EXISTS 选项来忽略这个异常。
      2、 EXTERNAL关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据
        的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;
        若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,
        内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
      3、 LIKE 允许用户复制现有的表结构,但是不复制数据。
      4、 ROW FORMAT
        DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char]
        [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
        | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value,
        property_name=property_value, ...)]
        用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT
        或者 ROW FORMAT DELIMITED,将会使用自带的 SerDe。在建表的时候,用户还需要为表指定列,
        用户在指定表的列的同时也会指定自定义的 SerDe,Hive通过 SerDe 确定表的具体的列的数据。
      5、 STORED AS
        SEQUENCEFILE|TEXTFILE|RCFILE
        如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,
        使用 STORED AS SEQUENCEFILE。

      6、CLUSTERED BY
        对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据
        范围划分。Hive也是 针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方
        式决定该条记录存放在哪个桶当中。
        把表(或者分区)组织成桶(Bucket)有两个理由:
        (1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。
          具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接
          (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,
          如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,
          可以大大较少JOIN的数据量。
        (2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在
          数据集的一小部分数据上试运行查询,会带来很多方便。


      7、创建内部表
        create table if not exists mytable(sid int,sname string)
        row format delimited fields terminated by '\005' stored as textfile

        创建外部表
        create external table if not exists pageview(pageid int,page_url string
        comment 'The page URL')
        row format delimited fields terminated by ','
        location 'hdfs://mini1:9000/user/hive/warehouse/'

        创建分区表
        create table student_p(Sno int,Sname string,Sex string,Sage int,Sdept string)
        partition by(part string) row format delimited fields terminated by ',' stored as textfile;

        创建带桶表
        create table student(id int,age int,name string)
        partitioned by(stat_date string)
        clustered by(id) sorted by (age) into 2 buckets
        row format delimited fields terminated by ',';

      8、修改表
        增加/删除分区
        语法结构
          ALTER TABLE table_name ADD [IF NOT EXISTS] partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ...
          partition_spec:
          : PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...)

          ALTER TABLE table_name DROP partition_spec, partition_spec,...

        具体实例
          alter table student_p add partition(part='a') partition(part='b');

          alter table student add partition(stat_date='20140101') location '/user/hive/warehouse/student' partition(stat_date='20140102')

      9、重命名表
        alter table table_name rename to new_table_name;


      10、增加/更新列
        语法结构
          ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)

          注:ADD是代表新增一字段,字段位置在所有列后面(partition列前),REPLACE则是表示替换表中所有字段。

          ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type
          [COMMENT col_comment] [FIRST|AFTER column_name]

      11、显示命令
 

show tables
         show databases
         show partitions
         show functions
         desc extended t_name;
         desc formatted table_name;


  3.2、DML操作
    1、Load
      语法结构
        load data [local] inpath 'filepath' [overwrite] into
        table tablename [partition(partcol1=val1,partcol2=val2...)]
      说明:
      1、 Load 操作只是单纯的复制/移动操作,将数据文件移动到 Hive 表对应的位置。
      2、 filepath:
        相对路径,例如:project/data1
        绝对路径,例如:/user/hive/project/data1
        包含模式的完整 URI,列如:
        hdfs://namenode:9000/user/hive/project/data1
      3、 LOCAL关键字
        如果指定了 LOCAL, load 命令会去查找本地文件系统中的 filepath。
        如果没有指定 LOCAL 关键字,则根据inpath中的uri 查找文件

        uri:如果指定了 LOCAL,那么:
        load 命令会去查找本地文件系统中的 filepath。如果发现是相对路径,则路径会被解释为相对于
        当前用户的当前路径。
        load 命令会将 filepath中的文件复制到目标文件系统中。目标文件系统由表的位置属性决定。
        被复制的数据文件移动到表的数据对应的位置。

        如果没有指定 LOCAL 关键字,如果 filepath 指向的是一个完整的 URI,hive 会直接使用这个 URI。 否则:如果没有指定 schema 或者 authority,Hive 会使用在 hadoop 配置文件中定义的 schema 和 authority,fs.default.name 指定了 Namenode 的 URI。
        如果路径不是绝对的,Hive 相对于/user/进行解释。
        Hive 会将 filepath 中指定的文件内容移动到 table (或者 partition)所指定的路径中。

      4、 OVERWRITE 关键字
        如果使用了 OVERWRITE 关键字,则目标表(或者分区)中的内容会被删除,然后再将 filepath 指向的文
        件/目录中的内容添加到表/分区中。
        如果目标表(分区)已经有一个文件,并且文件名和 filepath 中的文件名冲突,那么现有的文件会被
        新文件所替代。


      5、具体实例
        1\加载相对路径数据
          load data local inpath 'buckets.txt' into table student partition(stat_date='20131231')
        2\加载绝对路径数据
          load data local inpath '/root/app/datafile/buckets.txt' into table student partition(stat_date='20131231');
        3\加载包含模式数据
          load data local inpath 'hdfs://mini1:9000/user/hive/warehouse/student/stat_date=20131230/buckets.txt'
        4\overwrite
          load data local inpath 'buckets.txt' overwrite into table student parttition(stat_date='20131229');

    2、Insert
      语法结构
       

INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] 
         select_statement1 FROM from_statement         Multiple inserts:
         FROM from_statement 
         INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] 
         select_statement1 
         [INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ...         Dynamic partition inserts:
         INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) 
         select_statement FROM from_statement

      具体实例:
      基本模式插入
     

insert overwrite table student partition(stat_date='20140101')
         select id,age,name from student where stat_date='20131229'



      多插入模式插入
      

from student 
         insert overwrite table student partition(stat_date='20140102')
         select id,age,name where stat_date ='20131229'
         insert overwrite table student partition(stat_date='20140103')
         select id,age,name where stat_date ='20131229'


      自动分区模式
      

insert overwrite table student partition(stat_date)
         select id,age,name,stat_date from student where stat_date='20140101'



      3导出表数据
        语法结构
    

INSERT OVERWRITE [LOCAL] DIRECTORY directory1 SELECT ... FROM ...

         multiple inserts:
         FROM from_statement
         INSERT OVERWRITE [LOCAL] DIRECTORY directory1 select_statement1
         [INSERT OVERWRITE [LOCAL] DIRECTORY directory2 select_statement2] ...

        具体实例
        1、导出数据到本地
          insert overwrite local directory '/root/app/datafile/student'
          select * from student
          数据写入到文件系统时进行文本序列化,且每列用^A来区分,\n为换行符。
          用more命令查看时不容易看出分割符,可以使用: sed -e 's/\x01/|/g' filename 来查看。

        2、导出数据到hdfs
         

insert overwrite directory 'hdfs://mini1:9000/user/hive/warehouse/mystudent'
           select * from student;



    4、Select
      语法结构
    

SELECT [ALL | DISTINCT] select_expr, select_expr, ... 
       FROM table_reference
       [WHERE where_condition] 
       [GROUP BY col_list [HAVING condition]] 
       [CLUSTER BY col_list 
       | [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list] 
       ] 
       [LIMIT number]


      注:1、order by会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时
      ,需要较长的计算时间
      2、sort by 不是全局排序,其在数据进入reduce前完成排序,因此如果用sort by进行排序
      并且设置mapred.reduce.task>1,则sort by 只保证每个reducer的输出有序,不保证全局有序
      3、distribute by 根据distribute by 指定的内容将数据分到同一个reducer
      4、Cluster by除了具有distribute by 的功能外,还会对该字段进行排序,因此,常常认为cluster
        by=distribute by + sort by

    5、Hive Join
      语法结构
      join_table:
      table_reference 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
      Hive 支持等值连接(equality joins)、外连接(outer joins)和(left/right joins)。
      Hive 不支持非等值的连接,因为非等值连接非常难转化到 map/reduce 任务。
      另外,Hive 支持多于 2 个表的连接。

      LEFT SEMI JOIN是IN/EXISTS的高效实现。


6、Hive Shell参数
  Hive自定义函数和Transform
  自定义函数类别
  UDF 作用于单个数据行,产生一个数据行作为输出。(数学函数,字符串函数)
  UDAF(用户定义聚集函数):接收多个输入数据行,并产生一个输出数据行。(count,max)

  UDF开发实例
    1、先开发一个java类,继承UDF,并重载evaluate方法
    2、打成jar包上传到服务器
    3、将jar包添加到hive的classpath
    hive>add JAR /home/hadoop/udf.jar;
  4、创建临时函数与开发好的java class关联
    Hive>create temporary function toprovince as 'cn.itcast.bigdata.udf.ToProvince';

  5、即可在hql中使用自定义的函数strip
    Select strip(name),age from t_test;

  Transform实现
    Hive的 TRANSFORM 关键字提供了在SQL中调用自写脚本的功能
    适合实现Hive中没有的功能又不想写UDF的情况