Hive DDL&DML&DQL

Hive的DDL操作

创建数据库

语法

CREATE (DATABASE|SCHEMA) [IF NOT EXISTS] database_name
  [COMMENT database_comment]
  [LOCATION hdfs_path]
  [WITH DBPROPERTIES (property_name=property_value, ...)];

创建数据库,存储在HDFS的默认路径是/user/hive/warehouse/*.db

避免要创建的数据库已经存在错误,增加if not exists判断。(标准写法)

hive (default)> create database if not exists db_hive1;

hive中可以指定数据库在HDFS的存储路径,只需要指定location的参数即可

hive (default)> create database db_hive2 location '/tmp';

数据库操作

查询数据库

hive (default)> show databases;

OK
database_name
db_hive1
default
Time taken: 0.015 seconds, Fetched: 2 row(s)

过滤查询数据库

hive (default)> show databases like 'db_*';

OK
database_name
db_hive1
Time taken: 0.021 seconds, Fetched: 1 row(s)

切换数据库

hive (default)> use db_hive1;
OK
Time taken: 0.015 seconds

修改数据库

ALTER (DATABASE|SCHEMA) database_name SET DBPROPERTIES (property_name=property_value, ...);   -- (Note: SCHEMA added in Hive 0.14.0)

ALTER (DATABASE|SCHEMA) database_name SET OWNER [USER|ROLE] user_or_role;   -- (Note: Hive 0.13.0 and later; SCHEMA added in Hive 0.14.0)

ALTER (DATABASE|SCHEMA) database_name SET LOCATION hdfs_path; -- (Note: Hive 2.2.1, 2.4.0 and later)

删除数据库

DROP (DATABASE|SCHEMA) [IF EXISTS] database_name [RESTRICT|CASCADE];

如果删除的数据库不存在,避免报错采用 if exists判断数据库是否存在

hive (db_hive1)> drop database if exists db_test;
OK
Time taken: 0.2 seconds

如果数据库下面有表的存在,是删不掉的,使用cascade命令强制级联删除

hive (db_hive1)> drop database if exists db_test cascade;
OK
Time taken: 0.2 seconds

表操作

创建表
语法

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]
[TBLPROPERTIES (property_name=property_value, ...)]
[AS select_statement]

参数解析

  • EXTERNAL:表示创建一个外部表,外部表在删表的时候只会删除元数据而不会删除数据;内部表在删除的时候,元数据和数据都会删除

  • COMMENT:为表的列添加注释

  • PARTITIONED BY:创建分区表

  • CLUSTERED BY:创建分桶表

  • ROW FORMAT:指定列与列之间的分隔字符,比如使用table分割 ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’

      DELIMITED [FIELDS TERMINATED BY char]
    
  • STORED AS:指定存储文件类型常用的存储文件类型

SEQUENCEFILE(二进制序列文件)、TEXTFILE(文本)、RCFILE(列式存储格式文件),如果文件数据是纯文本,可以使用STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCEFILE。

  • LOCATION:表在HDFS上的存储路径
  • AS:后跟查询语句,根据查询结果创建表
  • LIKE:根据一个已存在的表创建另一个表,但是不复制数据

创建普通表指定列分隔符为‘\t’,并指定存储路径

CREATE TABLE emp_test1(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/bigdata/';

查看表

查看表

hive (db_hive1)> show tables;
OK
tab_name
emp_test1
Time taken: 0.082 seconds, Fetched: 1 row(s)

查看指定数据库中的表

hive (default)> show tables in db_hive1;

模糊查询查看表

hive (db_hive1)> show tables like 'emp*'

查看表字段信息

hive (db_hive1)> desc emp_test1;
OK
col_name        data_type       comment
empno                   int                                         
ename                   string                                      
job                     string                                      
mgr                     int                                         
hiredate                string                                      
sal                     double                                      
comm                    double                                      
deptno                  int                                         
Time taken: 0.132 seconds, Fetched: 8 row(s)

查看表的详细信息

hive (db_hive1)> desc formatted emp_test1;
OK
col_name        data_type       comment
# col_name              data_type               comment             
                 
empno                   int                                         
ename                   string                                      
job                     string                                      
mgr                     int                                         
hiredate                string                                      
sal                     double                                      
comm                    double                                      
deptno                  int                                         
                 
# Detailed Table Information             
Database:               db_hive1                 
OwnerType:              USER                     
Owner:                  hadoop                   
CreateTime:             Wed Dec 18 16:36:37 CST 2019     
LastAccessTime:         UNKNOWN                  
Protect Mode:           None                     
Retention:              0                        
Location:               hdfs://JD:9000/bigdata   
Table Type:             MANAGED_TABLE            
Table Parameters:                
        COLUMN_STATS_ACCURATE   true                
        numFiles                0                   
        numRows                 0                   
        rawDataSize             0                   
        totalSize               0                   
        transient_lastDdlTime   1576658516          
                 
# Storage Information            
SerDe Library:          org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe       
InputFormat:            org.apache.hadoop.mapred.TextInputFormat         
OutputFormat:           org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat       
Compressed:             No                       
Num Buckets:            -1                       
Bucket Columns:         []                       
Sort Columns:           []                       
Storage Desc Params:             
        field.delim             \t                  
        serialization.format    \t                  
Time taken: 0.085 seconds, Fetched: 40 row(s)

导入数据

其中加上local指的是在本地读数据,不加local是在hdfs上读数据

hive (db_hive1)> load data local inpath '/home/hadoop/data/emp.txt' into table emp_test1;
Loading data to table db_hive1.emp_test1
Table db_hive1.emp_test1 stats: [numFiles=0, numRows=0, totalSize=0, rawDataSize=0]
OK
Time taken: 0.427 seconds

根据查询结果创建表(创建的表和数据都有)

hive (db_hive1)> create table emp_test2 as select * from emp_test1;
。。。#跑mr程序

使用like创建表(只复制表结构)

hive (db_hive1)> create table emp_test3 like emp_test1;
OK
Time taken: 0.082 seconds

修改表

修改表的名称
hive (db_hive1)> alter table 
               > emp_test2 rename to emp_test3;
 

删除表

删除表
hive (db_hive1)> drop table emp_test;

清除表

清除表
hive (db_hive1)> truncate table emp_test1;

外部表和内部表

  • 外部表
    因为表是外部表,所以Hive并非认为其完全拥有这份数据。删除该表并不会删除掉这份数据,不过描述表的元数据信息会被删除掉

  • 外部表使用场景
    每天收集到的网站数据,需要做大量的统计数据分析,所以在数据源(即原始数据)上使用外部表进行存储,方便数据的共享,在做统计分析时候用到的中间表,结果表使用内部表,因为这些数据不需要共享,使用内部表更为合适。

  • 建表语句
    创建外部表

      CREATE EXTERNAL TABLE emp_test4(
      empno int,
      ename string,
      job string,
      mgr int,
      hiredate string,
      sal double,
      comm double,
      deptno int
      ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/bigdata/';
    
  • 删除表
    外部表被删除后只会删除元数据信息,数据不会删除

      hive (db_hive1)> drop table emp_test4;
    
  • 外部表与内部表的转换

    (‘EXTERNAL’=’TRUE’)和(‘EXTERNAL’=’FALSE’)为固定写法,只能大写,否则报错

    查看表的类型

      hive (db_hive1)> desc formatted emp_test3;
      Table Type:             MANAGED_TABLE #内部表
    

    修改emp_test3为外部表

      hive (db_hive1)> alter table emp_test3 set tblproperties('EXTERNAL'='TRUE');
      OK
      Time taken: 0.082 seconds
    

    查看修改后表的类型

      hive (db_hive1)> desc formatted emp_test3;
      Table Type:             EXTERNAL_TABLE 
    

    修改emp_test3为内部表

      hive (db_hive1)> alter table emp_test3 set tblproperties('EXTERNAL'='FALSE');
    

    查看修改后表的类型

      hive (db_hive1)> desc formatted emp_test3;
      Table Type:            MANAGED_TABLE 
    

分区表

概念

分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多。

优点

节省磁盘IO和网络IO,因为查是在磁盘查询,跑mr程序有网络的传输,消耗网络IO

建表语句

create table order_partition(
order_no string,
event_time string
)
PARTITIONED BY (event_month string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
  • 加载数据到分区表
    加载数据的时候一定要指定分区字段,对于分区操作如果数据直接写入hdfs没有通过hive写入,通过hive查询是查询不出来的,因为元数据里没有
hive (db_hive1)> load data local inpath '/home/hadoop/data/order_created07.txt' into table order_partition partition(event_month='2014-05');

  • 添加分区
hive (db_hive1)> alter table order_partition add if not exists partition(event_month='2014-07'); 
OK
Time taken: 0.095 seconds
  • 查询分区
hive (db_hive1)> select * from order_partition where event_month='2014-05';
OK
order_partition.order_no        order_partition.event_time      order_partition.event_month
10703007267488  2014-05-01 06:01:12.334+01      2014-05
10101043505096  2014-05-01 07:28:12.342+01      2014-05
10103043509747  2014-05-01 07:50:12.33+01       2014-05
10103043501575  2014-05-01 09:27:12.33+01       2014-05
10104043514061  2014-05-01 09:03:12.324+01      2014-05
Time taken: 0.07 seconds, Fetched: 5 row(s)
  • 多分区联合查询
hive (db_hive1)> select * from order_partition where event_month='2014-07' or event_month='2014-05';
  • 查看表有多少个分区
hive (db_hive1)> show partitions order_partition;
OK
partition
event_month=2014-05
event_month=2014-07
Time taken: 0.153 seconds, Fetched: 2 row(s)
  • 多级分区
    单级分区:一层目录
    三级分区:三级目录

    建立两级分区表
    create table order_mulit_partition(
    order_no string,
    event_time string
    )
    partition by(event_month string, step string)
    row format delimited fields terminated by ‘\t’;

  • 加载数据到二级分区表中

hive (db_hive1)> load data local inpath '/home/hadoop/data/order_created.txt' into table order_mulit_partition partition(event_month='2014-05',step='1'); 

Loading data to table db_hive1.order_mulit_partition partition (event_month=2014-05, step=1)
Partition db_hive1.order_mulit_partition{event_month=2014-05, step=1} stats: [numFiles=1, numRows=0, totalSize=213, rawDataSize=0]
OK
Time taken: 0.969 seconds
  • 查二级询分区表数据
hive (db_hive1)> select * from order_mulit_partition where event_month='2014-05' and step='1';

把emp的数据加载到emp分区表中去,分区字段是deptno

建表语句
CREATE TABLE emp_partition(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double
) 
PARTITIONED BY (deptno int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

导入数据
INSERT OVERWRITE TABLE emp_partition PARTITION (deptno=10) select empno,ename,job,mgr,hiredate,sal,comm   from emp where deptno=10;


动态分区

建表
CREATE TABLE emp_dynamic_partition(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double
) 
PARTITIONED BY (deptno int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

动态导入数据,其中deptno放在查询字段的最后,并与partition的deptno字段名一样
INSERT OVERWRITE TABLE emp_dynamic_partition PARTITION (deptno) select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp;

把数据直接上传到分区目录上,让分区表和数据产生关联的三种方式

  • 上传数据后修复(生产上不要用msck,因为如果存在大量数据,会把服务器搞崩)

1、创建文件夹和上传数据

[hadoop@JD ~]$ hadoop fs -mkdir -p /user/hive/warehouse/db_hive1.db/order_mulit_partition/event_month=2014-06/step=2

19/12/19 15:15:36 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
[hadoop@JD ~]$ hadoop fs -put '/home/hadoop/data/order_created.txt' '/user/hive/warehouse/db_hive1.db/order_mulit_partition/event_month=2014-06/step=2'   

19/12/19 15:16:55 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

2、查询数据(查不到上传的数据)

hive (db_hive1)> select * from order_mulit_partition where event_month='2014-06' and step='2';

OK
order_mulit_partition.order_no  order_mulit_partition.event_time        order_mulit_partition.event_month       order_mulit_partition.step
Time taken: 0.058 seconds

3、执行修复命令

hive (db_hive1)> msck repair table order_mulit_partition;

OK
Partitions not in metastore:    order_mulit_partition:event_month=2014-06/step=2
Repair: Added partition to metastore order_mulit_partition:event_month=2014-06/step=2
Time taken: 0.147 seconds, Fetched: 2 row(s)

4、再次查询

hive (db_hive1)> select * from order_mulit_partition where event_month='2014-06' and step='2';

OK
order_mulit_partition.order_no  order_mulit_partition.event_time        order_mulit_partition.event_month       order_mulit_partition.step
10703007267488  2014-05-01 06:01:12.334+01      2014-06 2
10101043505096  2014-05-01 07:28:12.342+01      2014-06 2
10103043509747  2014-05-01 07:50:12.33+01       2014-06 2
10103043501575  2014-05-01 09:27:12.33+01       2014-06 2
10104043514061  2014-05-01 09:03:12.324+01      2014-06 2
Time taken: 0.056 seconds, Fetched: 5 row(s)
  • 上传数据后添加分区(推荐方式)
    1、上传数据
[hadoop@JD ~]$ hadoop fs -mkdir -p /user/hive/warehouse/db_hive1.db/order_mulit_partition/event_month=2014-07/step=3

19/12/19 15:23:43 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
[hadoop@JD ~]$ 
[hadoop@JD ~]$ hadoop fs -put '/home/hadoop/data/order_created.txt' '/user/hive/warehouse/db_hive1.db/order_mulit_partition/event_month=2014-07/step=3'

19/12/19 15:23:52 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

2、添加分区(添加分区信息到元数据中)

hive (db_hive1)> alter table order_mulit_partition  add partition(event_month='2014-07',step='3');
OK
Time taken: 0.083 seconds

3、查询

hive (db_hive1)> select * from order_mulit_partition where event_month='2014-07' and step='3';

OK
order_mulit_partition.order_no  order_mulit_partition.event_time        order_mulit_partition.event_month       order_mulit_partition.step
10703007267488  2014-05-01 06:01:12.334+01      2014-07 3
10101043505096  2014-05-01 07:28:12.342+01      2014-07 3
10103043509747  2014-05-01 07:50:12.33+01       2014-07 3
10103043501575  2014-05-01 09:27:12.33+01       2014-07 3
10104043514061  2014-05-01 09:03:12.324+01      2014-07 3
Time taken: 0.053 seconds, Fetched: 5 row(s)
  • 创建文件夹后load数据到分区
    1、创建文件夹
[hadoop@JD ~]$ hadoop fs -mkdir -p /user/hive/warehouse/db_hive1.db/order_mulit_partition/event_month=2014-08/step=4

19/12/19 15:23:43 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

2、load数据

hive (db_hive1)> load data local inpath '/home/hadoop/data/order_created.txt' into table
 order_mulit_partition partition(month='2014-08',step='4');

3、查询数据

hive (db_hive1)> select * from order_mulit_partition where month='2014-08' and step='4';

DML操作

LOAD DATA : 加载数据
LOCAL: “本地” 没有的话就HDFS
INPATH: 指定路径
OVERWRITE:数据覆盖 没有的话就是追加

LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]

向表中load数据

导入本地文件

hive (db_hive1)> load data local inpath '/home/hadoop/data/emp.txt' into table emp_test2;

导入hdfs上的文件

hive (db_hive1)> load data inpath '/hive/hadoop/emp.txt' into table emp_test2;

覆盖表中已有的数据

hive (db_hive1)> load data local inpath '/home/hadoop/data/emp.txt' overwrite into table emp_test2;

通过insert语句插入数据

基本插入数据

1、创建分区表

create table order_partition1(
order_no string,
event_time string
)
PARTITIONED BY (event_month string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

2、插入数据

hive (db_hive1)> insert into table order_partition1 partition(event_month='2014-05') values('1','1111'),('2','2222');

根据查询结果插入数据

insert into: 以追加数据的方式插入到表或分区,原有数据不会删除
insert overwrite: 会覆盖表或分区中已存在的数据
注意: insert不支持插入部分字段

hive (db_hive1)> insert overwrite table order_partition1 partition(event_month='2014-06') select order_no,event_time from order_partition1 where event_month='2014-05';
  • 多表(多分区)插入模式(根据多张表查询结果)
hive (db_hive1)> from order_partition1
              insert overwrite table order_partition1 partition(month='2014-07')
              select id, name where month='2014-05'
              insert overwrite table order_partition1 partition(month='2014-08')
              select id, name where month='2014-05';

CTAS create table … as select…

根据查询结果创建表并导入数据(工作常用),表不能事先存在

create table if not exists student3 as select id, name from student;

insert:表必须事先存在

根据查询结果向表中插入数据
insert overwrite table emp4 select * from emp;

或者还有一种反人类的语法
from emp insert into table emp4 select *;

创建表时通过Location指定加载数据路径

1、先hdfs上传数据

[hadoop@JD ~]$ hadoop fs -mkdir /emp;
[hadoop@JD ~]hadoop fs -put /home/hadoop/data/emp.txt /emp;

2、建表并指定路径

hive (default)> create external table if not exists emp(
              id int, 
			  name string
              )
              row format delimited fields terminated by '\t'
              location '/emp;

3、查询

hive (default)> select * from emp;

数据导出

导入到本地文件,并指定分隔符
INSERT OVERWRITE local DIRECTORY '/hivetmp' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' SELECT empno,ename FROM emp;	 

导入到HDFS文件,并指定分隔符
INSERT OVERWRITE DIRECTORY '/hivetmp' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' SELECT empno,ename FROM emp;	

或者直接使用hdfs fs -get 命令

或者使用hive的交互式命令,然后重定向到本地
hive -e 'select empno,ename from emp'> 1.txt

如果过滤查询结果,使用grep
hive -e 'select empno,ename from emp | grep xxx'> 1.txt

Hive DQL

语法:

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]

WHERE

过滤筛选
查询区间使用between
查字符串在xxx之间使用in
查询为空的字段 is null
分区表必须加分区限制

ALL和DISTINCT

ALL和DISTINCT选项指定了是否返回重复值,默认是ALL,指定DISTINCT时会剔除重复的结果。注意,从Hive1.1.0开始,Hive支持SELECT DISTINCT *。ALL and DISTINCT can also be used in a UNION clause – see Union Syntax for more information.

hive> SELECT col1, col2 FROM t1
    1 3
    1 3
    1 4
    2 5
hive> SELECT DISTINCT col1, col2 FROM t1
    1 3
    1 4
    2 5
hive> SELECT DISTINCT col1 FROM t1
    1
    2

基于分区的查询

一个Select如果没有指定分区,执行时会扫描全表。如果加了分区条件,则会只扫描对应分区的数据。对于存在大量分区数据的表,加不加分区条件的差别是很大的。若不增加分区,可能会引起资源被全占用,引起业务延迟。

# 普通查询限制分区
SELECT page_views.*
FROM page_views
WHERE page_views.date >= '2008-03-01' AND page_views.date <= '2008-03-31'

# 关联时限制分区
SELECT page_views.*
FROM page_views JOIN dim_users
  ON (page_views.user_id = dim_users.id AND page_views.date >= '2008-03-01' AND page_views.date <= '2008-03-31')

HAVING

where和having的区别:

  • 使用场景:where可以用于select、update、delete和insert into values(select * from table where …)语句中。having只能用于select语句中。
  • 执行顺序:where的搜索条件是在执行语句进行分组之前应用;having的搜索条件是在分组条件后执行的。即如果where和having一起用时,where会先执行,having后执行。
  • 子句有区别:where子句中的条件表达式having都可以跟,而having子句中的有些表达式where不可以跟;having子句可以用集合函数(sum、count、avg、max和min),而where子句不可以。
  • 总结:
    1.WHERE 子句用来筛选 FROM 子句中指定的操作所产生的行。
    2.GROUP BY 子句用来分组 WHERE 子句的输出。
    3.HAVING 子句用来从分组的结果中筛选行
    以下两个等价
SELECT col1 FROM t1 GROUP BY col1 HAVING SUM(col2) > 10;
SELECT col1 FROM (SELECT col1, SUM(col2) AS col2sum FROM t1 GROUP BY col1) t2 WHERE t2.col2sum > 10;

聚合函数

聚合: 多进一出,select中出现的字段,如果没有出现在group by中,必须出现在聚合函数中
max
min
avg
count
sum

Hive SQL ,什么情况跑MR,什么情况不跑MR?

了解一个参数:hive.fetch.task.conversion,默认值是more.
以下面语句为例:

SQL1 : select * from live_info;
SQL2 : select * from live_info where traffic in ("1", "3");
SQL3 : select count(1) from live_info;
SQL4 : select user, count(1) as user_count from live_info group by user;
SQL5 : select user, count(1) as user_count from live_info group by user order by user desc;

fetch

参数:hive.fetch.task.conversion

value 官网解释 desc
none Disable hive.fetch.task.conversion select语句中只有desc不走MR
minimal SELECT *, FILTER on partition columns (WHERE and HAVING clauses), LIMIT only 仅SQL1 不走MR
more SELECT, FILTER, LIMIT only (including TABLESAMPLE, virtual columns) 仅SQL1、SQL2不走MR ,过滤条件是某一个字段的内容或limit或分区条件不跑mr
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章