表的分类
内部表(受控表)
表中数据的生命周期受到的表定义的影响,也就是说当表的定义被删除的时候,表中数据随之被删除。
内部表的字段表示:table_type: managed_table
可以通过desc extended tblName;来查看表的详细信息
外部表
表中数据的生命周期不受的表定义的影响,也就是说当表的定义被删除的时候,表中的数据依然存在。
外部表的字段表示:table_type: external_table
create external table t_external(id int);
drop table t_external;的时候发现,在hdfs上的数据依然存在==>
可以提高数据的安全性
create external table t_external_1(id int);
给外部表添加数据,基于引用的方式:
alter table t_external_1 set location “/data/hive-external.txt”;
在创建表的时候就来指定外部表的数据:
create external table t_external_2(id int) location “/data/”;
需要说明的是:在创建表的时候指定的数据路径,必须是一个目录。
外部表的好处:
可以提高数据的安全性
可以共享数据
外加两种功能表
分区表
/user/hive/warehouse/t
access.log.2016-10-30
access.log.2016-10-31
access.log.2016-11-01
access.log.2016-11-02
==>我们要向查询出access.log.2016-11-01,需要将这t目录下面的所有的数据加载到内存中,
然后通过where条件过滤出2016-11-01的数据,这样是非常消耗资源的。怎么来解决问题?
==>在/user/hive/warehouse/t目录下面,每天建立一个文件夹,同时把当天的access.log放到
这个文件夹下面
/user/hive/warehouse/t
/dt=2016-10-30
access.log.2016-10-30
/dt=2016-10-31
access.log.2016-10-31
/dt=2016-11-01
access.log.2016-11-01
/dt=2016-11-02
access.log.2016-11-02
create table t_partition(id int comment “学生ID”, name string comment “学生姓名”)
partitioned by(dt date comment “按照日期分区: yyyy-MM-dd”)
row format delimited
fields terminated by ‘\t’;
向分区表中加载数据
load data local inpath ‘/opt/data/hive-data/hive-partition.txt’ into table
t_partition partition(dt=”2016-10-31”);//他会自动的创建分区
查看某一个分区的数据
select * from t_partition where dt=”2016-10-31”;
将分区字段当做表的一个普通列来进行操作就可以了。
分区的DDL
查看分区:
show partitions t_partition;
手动添加分区:
alter table t_partition add partition(dt=”2016-11-03”);
手动删除分区:
alter table t_partition drop partition(dt=”2016-11-03”);
(删除分区,该分区的数据也将会被删除)
多个分区
*
create table t_partition_1(
id int comment “学生ID”,
name string comment “学生姓名”)
partitioned by(year int comment “入学年份”, class string comment “所学课程”)
row format delimited
fields terminated by ‘\t’;
加载数据::
load data local inpath ‘/opt/data/hive-data/hive-partition.txt’ into table t_partition_1 partition(year=2016, class=”linux”);
查询数据:
select * from t_partition_1 where year=2015;
select * from t_partition_1 where class=”bigdata” and year=2016;
桶表
桶表是对数据进行哈希取值,然后放到不同文件中存储。
create table t_bucket(id int) clustered by(id) into 3 buckets;
insert into table t_bucket select * from t_external_2 limit 5;
这样可以将数据分桶,新的版本中已经对去掉了hive.enforce.bucketing的参数,模式是开启分桶的。

hive的删除操作是insert 实现的
        insert overwrite table A select id,name from A where id !=2;

==============================================================================================社团()
本地模式
我们可以通过设置 hive.exec.mode.local.auto=true;开启本地是,会让MR在本地执行,不会到集群里面
去执行,这样可以提高执行的速率。
通常在做测试的时候,来使用本地模式,提高开发和调试的效率。
需要注意:桶表不支持本地模式!

看到我们使用set是对环境变量的临时性设置。只在当前会话有效,离开会话随机失效。

数据的加载和导出
[]==>可选,<> ==>必须
加载
load
load data [local] inpath ‘path’ [overwrite] into table [partition_psc];
local:
有==>从linux本地加载数据
无==>从hdfs加载数据
overwrite
有==>覆盖掉表中原来的数据
无==>在原来的基础上追加新的数据
从其他表加载
insert

group by w.word;

row_number:分组排序
        查询要求:见hive-demo
            按照部门查询出相应的员工信息,并且按照salary排序,从高到低。
                select
                 e.id, e.name, if(e.sex == 0, '女', '男') gender,d.name,
                 s.salary, row_number() over(partition by e.deptid order by s.salary desc) rank
                from t_dept d
                left join t_employee e on d.id = e.deptid
                left join t_salary s on e.id = s.empid
                where s.salary is not null;
            在上述基础之上,求出每个部门salary最高的两位
                只需要在上述的基础之上,将上述产生的结果作为中间表,过滤求出前两名
                select
                   temp.*
                from
                (select
                 e.id, e.name, if(e.sex == 0, '女', '男') gender,d.name,
                 s.salary, row_number() over(partition by e.deptid order by s.salary desc) rank
                from t_dept d
                left join t_employee e on d.id = e.deptid
                left join t_salary s on e.id = s.empid
                where s.salary is not null) temp
                where temp.rank < 3;

其中员工信息包含:emp-id,name,salary,sex(需要使用男或女),部门名称

collect_set
    3°、行转列
        第一步:做表关联,分析结果
            select u.id, u.name, a.address from user u join address a on u.id = a.uid;
        第二步:对出现的多个结果按照id来拼接字符串
            select u.id, max(u.name), concat_ws("," collect_set(a.address)) as addr 
                from t11_user u join address a
                on u.id = a.id group by u.id;
    4°、列转行
        准备数据
        create table t_user_addr as
            select u.id, max(u.name), concat_ws("," collect_set(a.address)) as addr 
                    from t11_user u join address a
                    on u.id = a.id group by u.id;           
        就使用explode行数就可以了
        select explode(split(addr, ",") from t_user_addr;
        查看多个字段

select id, name, address from user_addr lateral view explode(split(addr, “,”)) a as address;

自定义的函数
    1°、编写自定义的函数类,同时需要继承Hive里面的自定义函数(UDF)
    2°、编写evaluate()完成具体的业务逻辑
    3°、打包好(demo.jar)放到hive服务器上
    4°、在hive客户端里面使用add jar /path/demo.jar将我们写好的demo.jar加载到hive的classpath(临时)
    5°、在hive客户端创建一个临时的函数
        create tempapory function 'function_name' as '自定义类的全类名';
    6°、drop tempapory function 'function_name';
    自定义函数来统计每个人生日所对应的星座和生肖

    pom.xml
        <properties>
           <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
           <hive-api.version>2.1.0</hive-api.version>
           <hadoop-api.version>2.6.4</hadoop-api.version>
           <hadoop-core.version>1.2.1</hadoop-core.version>
        </properties>

      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.apache.hadoop</groupId>
          <artifactId>hadoop-common</artifactId>
          <version>${hadoop-api.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.hadoop</groupId>
          <artifactId>hadoop-mapreduce-client-core</artifactId>
          <version>${hadoop-api.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.hadoop</groupId>
          <artifactId>hadoop-core</artifactId>
          <version>${hadoop-core.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.hive</groupId>
          <artifactId>hive-exec</artifactId>
          <version>${hive-api.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.hive</groupId>
          <artifactId>hive-serde</artifactId>
          <version>${hive-api.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.hive</groupId>
          <artifactId>hive-service</artifactId>
          <version>${hive-api.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.hive</groupId>
          <artifactId>hive-metastore</artifactId>
          <version>${hive-api.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.hive</groupId>
          <artifactId>hive-common</artifactId>
          <version>${hive-api.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.hive</groupId>
          <artifactId>hive-cli</artifactId>
          <version>${hive-api.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.hive</groupId>
          <artifactId>hive-jdbc</artifactId>
          <version>${hive-api.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.thrift</groupId>
          <artifactId>libfb303</artifactId>
          <version>0.9.0</version>
        </dependency>

Hive中文件的存储类型
hive中文件的存储类型,我们可以通过hive-site.xml配置文件的配置项(hive.default.fileformat)来获取

hive.default.fileformat
TextFile

Expects one of [textfile, sequencefile, rcfile, orc].
Default file format for CREATE TABLE statement. Users can explicitly override it by CREATE TABLE ... STORED AS [FORMAT]


1、TextFile
Hive默认格式,数据不做压缩,磁盘开销大,数据解析开销大。 可结合Gzip、Bzip2、Snappy等使用(系统自动检查,执行查询时自动解压),但使用这种方式,hive不会对数据进行切分,
从而无法对数据进行并行操作。
在执行之前开启压缩输出
set hive.exec.compress.output=true;
set mapred.output.compress=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;/snappy/lz4/biz/default
set io.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
create table t_text(
line string
) stored as textfile;
2、SequenceFile
SequenceFile是Hadoop API提供的一种二进制文件支持,其具有使用方便、可分割、可压缩的特点。
SequenceFile支持三种压缩选择:NONE,RECORD,BLOCK。Record压缩率低,一般建议使用BLOCK压缩。

set mapred.output.compression.type=BLOCK;(在上述的基础上来做的)
    create table t_sequence(
        line string
    ) stored as sequencefile;
    insert overwrite table t_sequence select * from t_text;
    发现数据被大幅度的压缩
3、RCFile
    RCFILE是一种行列存储相结合的存储方式。首先,其将数据按行分块,保证同一个record在一个块上,避免读一个记录需要读取多个block。其次,块数据列式存储,有利于数据压缩和快速的列存取。
    create table t_rcfile(
        line string
    ) stored as rcfile;
    insert overwrite table t_rcfile select * from t_text;

总结:
    textfile 存储空间消耗比较大,并且压缩的text 无法分割和合并 查询的效率最低,可以直接存储,加载数据的速度最高
    sequencefile 存储空间消耗大,压缩的文件可以分割和合并 查询效率高,需要通过text文件转化来加载
    rcfile 存储空间最小,查询的效率最高 ,需要通过text文件转化来加载,加载的速度最低
    相比TEXTFILE和SEQUENCEFILE,RCFILE由于列式存储方式,数据加载时性能消耗较大,但是具有较好的压缩比和查询响应。数据仓库的特点是一次写入、多次读取,因此,整体来看,RCFILE相比其余两种格式具有较明显的优势。

在上述的过程中遇到一个问题:
    SequenceFile doesn't work with GzipCodesc without native-hadoop code!
    原因:
        这是因为默认的hadoop安装包是不支持压缩的,需要我们编译过之后才可以,
        当然我们也可以使用命令hadoop checknative -a检测一下可以使用的压缩依赖lib库,结果发现,都不支持,令人非常沮丧!!!
    解决:
        我们就可以将编译过的hadoop的lib($HADOOP_HOME/lib/native)包覆盖掉原来的(最好把之前的备份),
        再来执行就可以了。   

select count(1) from t_txt;
                104.5 M         36.189 
select count(1) from t_seq;
                582.6 K         34.92
select count(1) from t_rc;
                527.3 K         35.659 
select count(1) from t_orc;
                4.5 K           36.562
==>1000005