Hive-1.2.0学习笔记(四)Hive表管理

鲁春利的工作笔记,谁说程序员不能有文艺范?


Hive默认只有一个数据库default,并且默认的文件存储路径由配置文件hive-default.xml文件指定。

<property>
    <name>hive.metastore.warehouse.dir</name>
    <value>/user/hive/warehouse</value>
    <description>location of default database for the warehouse</description>
</property>

查看hdfs上的存储

[hadoop@nnode hive1.2.0]$ hdfs dfs -ls -R /user/hive
drwxrw-rw-   - hadoop hadoop          0 2015-12-13 12:45 /user/hive/warehouse
drwxrw-rw-   - hadoop hadoop          0 2015-12-09 00:12 /user/hive/warehouse/mywork.db
drwxrw-rw-   - hadoop hadoop          0 2015-12-09 00:00 /user/hive/warehouse/mywork.db/employee
-rwxrw-rw-   2 hadoop hadoop         83 2015-12-09 00:00 /user/hive/warehouse/mywork.db/employee/data_default.txt
drwxrw-rw-   - hadoop hadoop          0 2015-12-09 00:14 /user/hive/warehouse/mywork.db/employee_02
-rwxrw-rw-   2 hadoop hadoop         99 2015-12-09 00:14 /user/hive/warehouse/mywork.db/employee_02/data_employee02.txt
drwxrw-rw-   - hadoop hadoop          0 2015-12-08 23:03 /user/hive/warehouse/mywork.db/student


-- 创建数据库

# 创建数据库
hive> CREATE DATABASE mydb COMMENT 'This is my sample db' LOCATION '/user/hive/mydb'
      WITH DBPROPERTIES ('creator' =  'luchunli', 'date' = '2015-12-13');
OK
Time taken: 0.154 seconds
hive> 

# 查看元数据信息
mysql> select * from dbs;
+-------+-----------------------+----------------------------------------------+---------+------------+------------+
| DB_ID | DESC                  | DB_LOCATION_URI                              | NAME    | OWNER_NAME | OWNER_TYPE |
+-------+-----------------------+----------------------------------------------+---------+------------+------------+
|     1 | Default Hive database | hdfs://cluster/user/hive/warehouse           | default | public     | ROLE       |
|     6 | MyWork in hive        | hdfs://cluster/user/hive/warehouse/mywork.db | mywork  | hadoop     | USER       |
|    12 | This is my sample db  | hdfs://cluster/user/hive/mydb                | mydb    | hadoop     | USER       |
+-------+-----------------------+----------------------------------------------+---------+------------+------------+
3 rows in set (0.00 sec)

# 查看描述信息,extended可选
hive> describe database extended mydb;
OK
mydb    This is my sample db    hdfs://cluster/user/hive/mydb   hadoop  USER    {date=2015-12-13, creator=luchunli}
Time taken: 0.051 seconds, Fetched: 1 row(s)

# 删除数据库,如果存在表的话需要级联删除
hive> DROPDATABASE [IF EXISTS]mydb [CASCADE];

# 修改配置的属性信息
hive> alter database mydb set dbproperties ('edit' = 'luchunli');
OK
Time taken: 0.234 seconds
hive>


Hive完整建表语句:

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name 
[(column_name data_type [COMMENT col_comment]), ......]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment]), ......]
[
    CLUSTERED BY (col_name, col_name, col_name, ......)
    [SORTED BY (col_name [ASC|DESC], ......) ]
    INTO num_buckets BUCKETS
]
[
    ROW FORMAT 
    delimited fields terminated by '\t'    -- 自定义列分隔符
    collection items terminated by ','     -- 自定义集合分隔符
    map keys terminated by ':'             -- 自定义map的key/value分隔符
    lines terminated by '\n'               -- 自定义换行符
]
[STORED AS file_format]
[LOCATION hdfs_path]
[like existing_table_name]
[SERDE serde_name]
[TBLPROPERTIES (property_name=property_value,...)]


1、内部表

    又称为管理表(Managed Table),通过create创建的表默认就是内部表(MANAGED TABLE)。

# 建表
hive> create table t_inner_table (id int, name string, vnumber float) 
    > row format delimited fields terminated by '\t' ;
OK
Time taken: 1.24 seconds
hive>

# 查看HDFS上的数据文件
[hadoop@nnode data]$ hdfs dfs -text /inner_employee.txt
1000    zhangsan        5000
2000    lisi    6000
[hadoop@nnode data]$ 

# 从HDFS上加载数据
hive> load data inpath '/inner_employee.txt' into table t_inner_table;
Loading data to table default.t_inner_table
Table default.t_inner_table stats: [numFiles=1, totalSize=34]
OK
Time taken: 1.204 seconds
hive> select * from t_inner_table;
OK
1000    zhangsan        5000.0
2000    lisi    6000.0
Time taken: 1.203 seconds, Fetched: 2 row(s)
hive>

# 查看hdfs上表对应的数据
[hadoop@nnode data]$ hdfs dfs -ls -R /user/hive/warehouse|grep t_inner
drwxrw-rw-   - hadoop hadoop          0 2015-12-13 14:13 /user/hive/warehouse/t_inner_table
-rwxrw-rw-   2 hadoop hadoop         34 2015-12-13 14:12 /user/hive/warehouse/t_inner_table/inner_employee.txt
[hadoop@nnode data]$

hive> drop table t_inner_table;
OK
Time taken: 0.917 seconds
hive>

说明:

    将hdfs上的数据load到表中之后,hdfs上原始文件就没有了,hive表对应的数据就是需要load数据的txt文件。

    drop table会把表对应的存储文件也删掉了。


总结:

    hive数据库对应的是hdfs的文件夹。

    hive表对应的是hdfs的文件夹。

    hive表中的数据对应的是hdfs的数据文件。

    hive表中的数据文件在metastore中是没有体现的。


2、外部表

    建表时使用external关键字标识为外部表。

# 创建外部表
hive> create table t_external_table (id int, name string, vnumber float) 
row format delimited fields terminated by '\t' ;

# 查看元数据信息
mysql> select tbl_id, db_id, owner, tbl_name, tbl_type from tbls;
+--------+-------+--------+------------------+----------------+
| tbl_id | db_id | owner  | tbl_name         | tbl_type       |
+--------+-------+--------+------------------+----------------+
|      6 |     6 | hadoop | student          | MANAGED_TABLE  |
|     11 |     6 | hadoop | employee         | MANAGED_TABLE  |
|     12 |     6 | hadoop | employee_02      | MANAGED_TABLE  |
|     26 |     1 | hadoop | t_external_table | EXTERNAL_TABLE |
+--------+-------+--------+------------------+----------------+
4 rows in set (0.00 sec)

mysql> 

# 加载数据
hive> load data inpath '/external_employee.txt' into table t_external_table;
Loading data to table default.t_external_table
Table default.t_external_table stats: [numFiles=1, totalSize=34]
OK
Time taken: 0.559 seconds
hive> select * from t_external_table;
OK
1000    zhangsan        5000.0
2000    lisi    6000.0
Time taken: 0.556 seconds, Fetched: 2 row(s)
hive>

#导入不符合格式要求的数据
[hadoop@nnode data]$ hdfs dfs -cat /invalid_data.txt
hello   world
hello you
hello me
[hadoop@nnode data]$ 

# 加载无效数据到hive的表中
hive> load data inpath '/invalid_data.txt' into table t_external_table;
Loading data to table default.t_external_table
Table default.t_external_table stats: [numFiles=2, totalSize=65]
OK
Time taken: 0.869 seconds
hive> select * from t_external_table;
OK
1000    zhangsan        5000.0
2000    lisi    6000.0
NULL    world   NULL
NULL    NULL    NULL
NULL    NULL    NULL
Time taken: 0.119 seconds, Fetched: 5 row(s)
hive>

# 查看hdfs上数据文件
[hadoop@nnode data]$ hdfs dfs -ls -R /user/hive/warehouse/|grep t_external
drwxrw-rw-   - hadoop hadoop          0 2015-12-13 16:00 /user/hive/warehouse/t_external_table
-rwxrw-rw-   2 hadoop hadoop         34 2015-12-13 15:50 /user/hive/warehouse/t_external_table/external_employee.txt
-rwxrw-rw-   2 hadoop hadoop         31 2015-12-13 15:58 /user/hive/warehouse/t_external_table/invalid_data.txt
[hadoop@nnode data]$ hdfs dfs -ls /|grep invalid    -- HDFS上已无该文件
[hadoop@nnode data]$

# 删除表
hive> drop table t_external_table;
OK
Time taken: 0.214 seconds
hive> 
# 但是hdfs上的数据仍然存在
[hadoop@nnode data]$ hdfs dfs -ls -R /user/hive/warehouse/|grep t_external
drwxrw-rw-   - hadoop hadoop          0 2015-12-13 16:00 /user/hive/warehouse/t_external_table
-rwxrw-rw-   2 hadoop hadoop         34 2015-12-13 15:50 /user/hive/warehouse/t_external_table/external_employee.txt
-rwxrw-rw-   2 hadoop hadoop         31 2015-12-13 15:58 /user/hive/warehouse/t_external_table/invalid_data.txt
[hadoop@nnode data]$ 
# 但mysql中元数据信息已经不存在了。

说明:

    Hive在导入数据时是不会对导入的数据格式进行检查的,这和MySQL、Oracle这种RDBMS是不一样的。传统的关系型数据库属于写模式(schema on write),即在写入数据时进行格式检查,可以保证数据查询的效率。而hive是针对大数据量进行处理的,每次可能都有大量的数据需要load,为了保证写入效率对数据不进行校验,但是在数据读取时进行校验,对于不兼容的数据类型直接处理为NULL,属于读模式(schema on read)

    这种读模式是Hive的实现机制,与外部表或内部表没关系,只是在外部表这里做了说明。外部表与内部表的区别只是在于删除表时,对应的数据文件是否删除。


3、分区表

hive中创建分区表没有什么复杂的分区类型(范围分区、列表分区、hash分区、混合分区等)。分区列也不是表中的一个实际的字段,而是一个或者多个伪列,即表的数据文件中实际上并不保存分区列的信息与数据。

创建分区表,由partitioned by指定分区字段

hive> create table t_access_log (
      interface int, imsi string, imei string, 
      msisdn string, userip string, lac string
    ) partitioned by (province string)        # 指定分区列
    row format delimited fields terminated by '\|';

加载数据到不同的分区

# 加载province为bj的分区数据
hive> load data inpath '/hive/data/bj_part_data.txt' 
    > into table t_access_log partition ( province='bj');
Loading data to table default.t_access_log partition (province=bj)
Partition default.t_access_log{province=bj} stats: [numFiles=1, numRows=0, totalSize=197, rawDataSize=0]
OK
Time taken: 0.712 seconds
hive> select * from t_access_log;
OK
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    bj
Time taken: 0.162 seconds, Fetched: 3 row(s)
hive> 
# 加载province为sh的分区数据,0.7版本之后分区不存在会自动创建
hive> load data inpath '/hive/data/sh_part_data.txt' 
    > into table t_access_log partition ( province='sh');
Loading data to table default.t_access_log partition (province=sh)
Partition default.t_access_log{province=sh} stats: [numFiles=1, numRows=0, totalSize=197, rawDataSize=0]
OK
Time taken: 0.705 seconds
# 查询所有数据
hive> select * from t_access_log;
OK
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    bj
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    sh
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    sh
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    sh
Time taken: 0.174 seconds, Fetched: 6 row(s)
# 根据分区条件查询数据
hive> select * from t_access_log where province = 'bj';
OK
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    bj
Time taken: 0.277 seconds, Fetched: 3 row(s)
hive> 
# 查看hdfs上的数据
[hadoop@nnode data]$ hdfs dfs -ls -R /user/hive/warehouse|grep t_access_log
drwxrw-rw-   - hadoop hadoop          0 2015-12-13 17:59 /user/hive/warehouse/t_access_log
drwxrw-rw-   - hadoop hadoop          0 2015-12-13 17:58 /user/hive/warehouse/t_access_log/province=bj
-rwxrw-rw-   2 hadoop hadoop        197 2015-12-13 17:58 /user/hive/warehouse/t_access_log/province=bj/bj_part_data.txt
drwxrw-rw-   - hadoop hadoop          0 2015-12-13 17:59 /user/hive/warehouse/t_access_log/province=sh
-rwxrw-rw-   2 hadoop hadoop        197 2015-12-13 17:43 /user/hive/warehouse/t_access_log/province=sh/sh_part_data.txt
[hadoop@nnode data]$

通过NameNode的web界面查看,每个分区对应一个独立的文件夹,下面为该分区的数据文件。

wKioL1ZtQrnD4fGBAAEgsS8ny2A928.jpg

    分区在存储时以目录形式存储,查询的时候就可以快速定位到某个目录下从而大大提高查询效率(减少了扫描的数据块的数量,MySQL的分区实际上在物理上也是这么存储的)。


新增及删除分区

# 新增及删除分区
hive> alter table t_access_log add partition (province = 'sd');
OK
Time taken: 0.308 seconds
hive> alter table t_access_log add partition (province = 'hn');
OK
Time taken: 0.228 seconds
hive> load data inpath '/hive/data/hn_part_data.txt' into table t_access_log partition ( province='hn');
Loading data to table default.t_access_log partition (province=hn)
Partition default.t_access_log{province=hn} stats: [numFiles=1, totalSize=197]
OK
Time taken: 0.923 seconds
hive> select * from t_access_log;
OK
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    bj
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    hn
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    hn
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    hn
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    sh
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    sh
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    sh
Time taken: 0.205 seconds, Fetched: 9 row(s)
hive> alter table t_access_log drop partition (province = 'hn');
Dropped the partition province=hn
OK
Time taken: 1.319 seconds
hive> select * from t_access_log;
OK
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    bj
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    sh
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    sh
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    sh
Time taken: 0.217 seconds, Fetched: 6 row(s)
hive>

说明:

    分区可以实现对原有固定分类数据的加载,这里是通过内部表实现,在实际的应用中最好还是通过外部表来实现(在删除表时不至于将原始数据删除)。

    比如我的业务中有按照年份/月份创建的数据目录,目录下为文本文件,可以通过该方式检索数据。

# 查看分区
Time taken: 0.217 seconds, Fetched: 6 row(s)
hive> show partitions t_access_log;
OK
province=bj
province=sd
province=sh
Time taken: 0.121 seconds, Fetched: 3 row(s)
hive>


4、动态分区

上述分区主要是按照省份进行分区,相对而言分区数目还不算多且分区值都能够确认。如果有一个分区表需要按照日期和省份进行创建分区表,每次执行insert操作时都手动指定分区值就太繁琐了,可以考虑使用动态分区。

使用动态分区要先设置hive.exec.dynamic.partition参数值为true。

hive> set hive.exec.dynamic.partition;
hive.exec.dynamic.partition=true    # 可以看到在当前版本中该值默认已经设置为true
hive> 

# 构造数据
[hadoop@nnode data]$ cat n_hn_part_data.txt 
1|460023426423051|862663023859426|8615042xxxxxx|10.82.210.200|4084|20151212|hn
1|460025405586412|865944022464088|8618340xxxxxx|10.76.89.70|40D0|20151213|hn
1|460025405586412|865944022464088|8618340xxxxxx|10.76.89.70|40D0|20151213|hn
[hadoop@nnode data]$ cat n_bj_part_data.txt 
1|460023426423051|862663023859426|8615042xxxxxx|10.82.210.200|4084|20151212|bj
1|460025405586412|865944022464088|8618340xxxxxx|10.76.89.70|40D0|20151213|bj
1|460025405586412|865944022464088|8618340xxxxxx|10.76.89.70|40D0|20151213|bj
[hadoop@nnode data]$ 

# 建普通表
hive> create table t_normal_table (
      interface int, imsi string, imei string, 
      msisdn string, userip string, lac string,
      statdate string, province string
    ) row format delimited fields terminated by '\|';

# 加载数据
hive> load data local inpath '${env:HIVE_HOME}/data/n_hn_part_data.txt' 
    > into table t_normal_table;
Loading data to table default.t_normal_table
Table default.t_normal_table stats: [numFiles=1, totalSize=233]
OK
Time taken: 0.363 seconds
hive> load data local inpath '${env:HIVE_HOME}/data/n_bj_part_data.txt' 
    > into table t_normal_table;
Loading data to table default.t_normal_table
Table default.t_normal_table stats: [numFiles=2, totalSize=466]
OK
Time taken: 0.32 seconds
hive> select * from t_normal_table;
OK
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    20151212        bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        bj
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    20151212        hn
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        hn
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        hn
Time taken: 0.12 seconds, Fetched: 6 row(s)
hive>

# 创建分区表
hive> create table t_multi_access_log (
      interface int, imsi string, imei string, 
      msisdn string, userip string, lac string
   ) partitioned by (statdate string, province string)
   row format delimited fields terminated by '\|';

# 装入数据到分区表
hive> insert overwrite table t_multi_access_log partition (statdate='20151213', province)
    > select interface, imsi, imei, msisdn, userip, lac, province 
    > from t_normal_table where statdate = '20151213';
Query ID = hadoop_20151213224140_4fb1623c-ff51-4033-b60e-7e442a04662c
Total jobs = 3
Launching Job 1 out of 3
Number of reduce tasks is set to 0 since there's no reduce operator
Starting Job = job_1449973138328_0003, Tracking URL = http://nnode:8088/proxy/application_1449973138328_0003/
Kill Command = /usr/local/hadoop2.6.0/bin/hadoop job  -kill job_1449973138328_0003
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 0
2015-12-13 22:42:23,020 Stage-1 map = 0%,  reduce = 0%
2015-12-13 22:43:08,507 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 3.36 sec
MapReduce Total cumulative CPU time: 3 seconds 360 msec
Ended Job = job_1449973138328_0003
Stage-4 is selected by condition resolver.
Stage-3 is filtered out by condition resolver.
Stage-5 is filtered out by condition resolver.
Moving data to: hdfs://cluster/user/hive/warehouse/t_multi_access_log/statdate=20151213/.hive-staging_hive_2015-12-13_22-41-40_947_3435826605781976430-1/-ext-10000
Loading data to table default.t_multi_access_log partition (statdate=20151213, province=null)
         Time taken for load dynamic partitions : 361
        Loading partition {statdate=20151213, province=hn}
        Loading partition {statdate=20151213, province=bj}
         Time taken for adding to write entity : 2
Partition default.t_multi_access_log{statdate=20151213, province=bj} stats: [numFiles=1, numRows=2, totalSize=130, rawDataSize=128]
Partition default.t_multi_access_log{statdate=20151213, province=hn} stats: [numFiles=1, numRows=2, totalSize=130, rawDataSize=128]
MapReduce Jobs Launched: 
Stage-Stage-1: Map: 1   Cumulative CPU: 3.36 sec   HDFS Read: 5631 HDFS Write: 449 SUCCESS
Total MapReduce CPU Time Spent: 3 seconds 360 msec
OK
Time taken: 90.696 seconds
hive> 

# 查看hive的数据文件
[hadoop@nnode data]$ hdfs dfs -ls -R /user/hive/warehouse/t_multi_access_log
drwxrw-rw-   - hadoop hadoop          0 2015-12-13 22:43 /user/hive/warehouse/t_multi_access_log/statdate=20151213
drwxrw-rw-   - hadoop hadoop          0 2015-12-13 22:43 /user/hive/warehouse/t_multi_access_log/statdate=20151213/province=bj
-rwxrw-rw-   2 hadoop hadoop        130 2015-12-13 22:43 /user/hive/warehouse/t_multi_access_log/statdate=20151213/province=bj/000000_0
drwxrw-rw-   - hadoop hadoop          0 2015-12-13 22:43 /user/hive/warehouse/t_multi_access_log/statdate=20151213/province=hn
-rwxrw-rw-   2 hadoop hadoop        130 2015-12-13 22:43 /user/hive/warehouse/t_multi_access_log/statdate=20151213/province=hn/000000_0
[hadoop@nnode data]$

注意,动态分区不允许主分区采用动态列而副分区采用静态列,这样将导致所有的主分区都要创建副分区静态列所定义的分区:

hive> truncate table t_multi_access_log;
OK
Time taken: 0.74 seconds
hive> insert overwrite table t_multi_access_log partition(statdate, province='bj')
    > select interface, imsi, imei, msisdn, userip, lac, province 
    > from t_normal_table where province = 'bj';
FAILED: SemanticException [Error 10094]: Line 1:52 Dynamic partition cannot 
be the parent of a static partition ''bj''
hive>


如果创建时主分区与子分区都不指定呢?

hive> insert overwrite table t_multi_access_log partition(statdate, province)
    > select interface, imsi, imei, msisdn, userip, lac, province 
    > from t_normal_table;
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
hive>

动态分区可以允许所有的分区列都是动态分区列,但要设置参数hive.exec.dynamic.partition.mode 。

hive> set hive.exec.dynamic.partition.mode;
hive.exec.dynamic.partition.mode=strict
hive>

它的默认值是strict,即不允许分区列全部是动态的,这是为了防止用户有可能原意是只在子分区内进行动态建分区,但是由于疏忽忘记为主分区列指定值了,这将导致一个dml语句在短时间内创建大量的新的分区(对应大量新的文件夹),对系统性能带来影响。

hive> set hive.exec.dynamic.partition.mode=nostrict;
hive> set hive.exec.dynamic.partition.mode;
hive.exec.dynamic.partition.mode=nostrict
hive>

数据导入

# 原始数据
hive> select * from t_normal_table;
OK
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    20151212        bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        bj
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    20151212        hn
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        hn
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        hn
Time taken: 0.22 seconds, Fetched: 6 row(s)
hive> 

# 执行导入的SQL,转化为MR执行
hive> insert overwrite table t_multi_access_log partition(statdate, province)
    > select interface, imsi, imei, msisdn, userip, lac, statdate, province 
    > from t_normal_table;
Query ID = hadoop_20151214225222_394ae95c-31e7-408d-825e-f44d003aca87
Total jobs = 3
Launching Job 1 out of 3
Number of reduce tasks is set to 0 since there's no reduce operator
Starting Job = job_1450103743864_0001, Tracking URL = http://nnode:8088/proxy/application_1450103743864_0001/
Kill Command = /usr/local/hadoop2.6.0/bin/hadoop job  -kill job_1450103743864_0001
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 0
2015-12-14 22:53:15,911 Stage-1 map = 0%,  reduce = 0%
2015-12-14 22:53:51,452 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.85 sec
MapReduce Total cumulative CPU time: 1 seconds 850 msec
Ended Job = job_1450103743864_0001
Stage-4 is selected by condition resolver.
Stage-3 is filtered out by condition resolver.
Stage-5 is filtered out by condition resolver.
Moving data to: hdfs://cluster/user/hive/warehouse/t_multi_access_log/.hive-staging_hive_2015-12-14_22-52-22_984_6874563132460931498-1/-ext-10000
Loading data to table default.t_multi_access_log partition (statdate=null, province=null)
         Time taken for load dynamic partitions : 1170
        Loading partition {statdate=20151212, province=hn}
        Loading partition {statdate=20151213, province=hn}
        Loading partition {statdate=20151213, province=bj}
        Loading partition {statdate=20151212, province=bj}
         Time taken for adding to write entity : 4
Partition default.t_multi_access_log{statdate=20151212, province=bj} stats: [numFiles=1, numRows=1, totalSize=67, rawDataSize=66]
Partition default.t_multi_access_log{statdate=20151212, province=hn} stats: [numFiles=1, numRows=1, totalSize=67, rawDataSize=66]
Partition default.t_multi_access_log{statdate=20151213, province=bj} stats: [numFiles=1, numRows=2, totalSize=130, rawDataSize=128]
Partition default.t_multi_access_log{statdate=20151213, province=hn} stats: [numFiles=1, numRows=2, totalSize=130, rawDataSize=128]
MapReduce Jobs Launched: 
Stage-Stage-1: Map: 1   Cumulative CPU: 1.85 sec   HDFS Read: 5210 HDFS Write: 733 SUCCESS
Total MapReduce CPU Time Spent: 1 seconds 850 msec
OK
Time taken: 93.123 seconds
hive> 
# 查看表中的数据
hive> select * from t_multi_access_log;
OK
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    20151212        bj
1       460023426423051 862663023859426 8615042xxxxxx   10.82.210.200   4084    20151212        hn
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        bj
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        hn
1       460025405586412 865944022464088 8618340xxxxxx   10.76.89.70     40D0    20151213        hn
Time taken: 0.156 seconds, Fetched: 6 row(s)
hive> 
# 在HDFS上生成的文件
[hadoop@nnode ~]$ hdfs dfs -ls -R /user/hive/warehouse|grep t_multi_access_log
drwxrw-rw-   - hadoop hadoop          0 2015-12-14 22:53 /user/hive/warehouse/t_multi_access_log
drwxrw-rw-   - hadoop hadoop          0 2015-12-14 22:53 /user/hive/warehouse/t_multi_access_log/statdate=20151212
drwxrw-rw-   - hadoop hadoop          0 2015-12-14 22:53 /user/hive/warehouse/t_multi_access_log/statdate=20151212/province=bj
-rwxrw-rw-   2 hadoop hadoop         67 2015-12-14 22:53 /user/hive/warehouse/t_multi_access_log/statdate=20151212/province=bj/000000_0
drwxrw-rw-   - hadoop hadoop          0 2015-12-14 22:53 /user/hive/warehouse/t_multi_access_log/statdate=20151212/province=hn
-rwxrw-rw-   2 hadoop hadoop         67 2015-12-14 22:53 /user/hive/warehouse/t_multi_access_log/statdate=20151212/province=hn/000000_0
drwxrw-rw-   - hadoop hadoop          0 2015-12-14 22:39 /user/hive/warehouse/t_multi_access_log/statdate=20151213
drwxrw-rw-   - hadoop hadoop          0 2015-12-14 22:53 /user/hive/warehouse/t_multi_access_log/statdate=20151213/province=bj
-rwxrw-rw-   2 hadoop hadoop        130 2015-12-14 22:53 /user/hive/warehouse/t_multi_access_log/statdate=20151213/province=bj/000000_0
drwxrw-rw-   - hadoop hadoop          0 2015-12-14 22:53 /user/hive/warehouse/t_multi_access_log/statdate=20151213/province=hn
-rwxrw-rw-   2 hadoop hadoop        130 2015-12-14 22:53 /user/hive/warehouse/t_multi_access_log/statdate=20151213/province=hn/000000_0
[hadoop@nnode ~]$ hdfs dfs -cat /user/hive/warehouse/t_multi_access_log/statdate=20151213/province=bj/000000_0
1|460025405586412|865944022464088|8618340xxxxxx|10.76.89.70|40D0
1|460025405586412|865944022464088|8618340xxxxxx|10.76.89.70|40D0
[hadoop@nnode ~]$

    说明:insert overwrite是覆盖,insert into是追加


5、桶表

桶是更为细粒度的数据范围划分,对于hive中的每一个table或partition table,可以进一步组织成桶(BUCKET)。桶操作是通过CLUSTERED BY实现的,BUCKET中的数据可以通过SORT BY排序。

Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。


BUCKET主要作用为:

    数据sampling;

    提升某些查询操作效率,如Map-Side Join。

注意:CLUSTERED BY和SORT BY不会影响数据的导入,即用户来控制数据的分桶和排序。


SORT BY

    不受hive.mapred.mode的值(nonstrict/strict)的影响,sort by的数据只能保证在同一个reduce中的数据可以按指定字段排序。

    使用sort by可以指定执行的Reduce个数(set mapred.reduce.tasks=<number>),可输出更多的数据(???)

wKioL1Zu38Thu7QaAAqZyKD4FOA870.jpg


DISTRIBUTE BY

    按照指定的字段将数据划分到不同的输出Reduce中。

hive> set mapreduce.job.reduces=2;

wKioL1Zu43jw6nZPAAkmPwYipks756.jpg

注意:

    这里是把表的数据导入到了本地磁盘的/home/hadoop/normal_table目录下,但只有一个文件有数据,不清楚原因。

[hadoop@nnode ~]$ ll normal_table/
total 4
-rw-r--r-- 1 hadoop hadoop   0 Dec 14 23:40 000000_0
-rw-r--r-- 1 hadoop hadoop 172 Dec 14 23:40 000001_0
[hadoop@nnode ~]$

CLUSTERED BY

    兼具distribute by和sort by的功能。


桶表示例

通过clustered by声明划分桶的列和桶的个数,示例通过statdate来分桶,划分出4个桶。hive会对statdate列计算hash值,再以桶的个数取模,确定记录属于哪一个桶。

hive> create table t_bucket_table (
      interface int, imsi string, imei string, statdate string
    ) clustered by (statdate) into 4 buckets;

# 导入数据
hive> insert into t_bucket_table
      select interface, imsi, imei, statdate from t_normal_table;
      
# 查看结果
hive> select * from t_bucket_table;
OK
1       460023426423051 862663023859426 20151212
1       460023426423051 862663023859426 20151212
1       460025405586412 865944022464088 20151213
1       460025405586412 865944022464088 20151213
1       460025405586412 865944022464088 20151213
1       460025405586412 865944022464088 20151213
Time taken: 0.141 seconds, Fetched: 6 row(s)
hive> 

# hdfs上的存储-分为了四个数据文件
[hadoop@nnode normal_table]$ hdfs dfs -ls -R /user/hive/warehouse|grep t_bucket_table
drwxrw-rw-   - hadoop hadoop          0 2015-12-14 23:53 /user/hive/warehouse/t_bucket_table
-rwxrw-rw-   2 hadoop hadoop         86 2015-12-14 23:53 /user/hive/warehouse/t_bucket_table/000000_0
-rwxrw-rw-   2 hadoop hadoop        172 2015-12-14 23:53 /user/hive/warehouse/t_bucket_table/000001_0
-rwxrw-rw-   2 hadoop hadoop          0 2015-12-14 23:53 /user/hive/warehouse/t_bucket_table/000002_0
-rwxrw-rw-   2 hadoop hadoop          0 2015-12-14 23:53 /user/hive/warehouse/t_bucket_table/000003_0
[hadoop@nnode normal_table]$ hdfs dfs -text /user/hive/warehouse/t_bucket_table/000000_0
146002342642305186266302385942620151212
146002342642305186266302385942620151212
[hadoop@nnode normal_table]$ hdfs dfs -text /user/hive/warehouse/t_bucket_table/000001_0
146002540558641286594402246408820151213
146002540558641286594402246408820151213
146002540558641286594402246408820151213
146002540558641286594402246408820151213
[hadoop@nnode normal_table]$

    注意:hive> set hive.enforce.bucketing=true

    �C必须设置这个数据,hive才会按照你设置的桶的个数去生成数据

    insert overwrite是覆盖,insert into是追加


上面的操作是对表执行分桶,如果是基于partition再bucket呢?

hive> create table t_bucket_table_of_part (
      interface int, imsi string, imei string, 
      msisdn string, userip string, lac string
   ) partitioned by (statdate string, province string)
   clustered by (lac) sorted by (lac) into 4 buckets 
   row format delimited fields terminated by '\|';

抽样查询

tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y)

y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。
    例如,table总共分了64份
        当y=32时,抽取 (64/32=)2个bucket的数据,
        当y=128时,抽取(64/128=)1/2个bucket的数据。
x表示从哪个bucket开始抽取。
    例如,table总bucket数为32,tablesample(bucket 3 out of 16),
    表示总共抽取(32/16=)2个bucket的数据,分别为第3个bucket和第(3+16=)19个bucket的数据。

SELECT * FROM t_bucket_table_of_part  TABLESAMPLE (BUCKET 1 OUT OF 2 ON statdate);

    表示抽取2个(4/2)bucket的数据,分别为第1个和第3(1+2)个。


6、导出表中数据

如果数据文件恰好是用户需要的格式,只需要简单的将文件或文件夹通过hdfs命令复制出来即可。

[hadoop@nnode data]$ hdfs dfs -get /user/hive/warehouse/t_access_log/province=sh/sh_part_data.txt backup_sh_part_data.txt

[hadoop@nnode data]$ cat backup_sh_part_data.txt 
1|460023426423051|862663023859426|8615042xxxxxx|10.82.210.200|4084
1|460025405586412|865944022464088|8618340xxxxxx|10.76.89.70|40D0
1|460025405586412|865944022464088|8618340xxxxxx|10.76.89.70|40D0
[hadoop@nnode data]$


insert overwrite local directory  '...' sql clause


from table table_name 别名

    insert overwrite local directory  '...' select 别名.列名 clause

    insert overwrite local directory  '...' select 别名.列名 clause

    insert overwrite local directory  '...' select 别名.列名 clause

类似于插入。


7、视图操作

    Hive0.6版本开始支持视图,但暂不支持物化视图,其具体使用方式与MySQL类似。


8、索引管理

    Hive0.7版本开始支持索引,暂略,使用到了再补充。


你可能感兴趣的:(hive,table)