Hive建表语句、内部表vs外部表、加载数据


一、Hive 查看SQL解析计划

#extended:展开。可选,可以打印更多细节
#explain:解释
#在最前端加个explain,查看SQL解析计划
explain [extended] select  a.id
        ,a.name
        ,a.clazz
        ,t1.sum_score
from(
    select  id
            ,sum(score) as sum_score
    from score 
    group by id
)t1 right join (
    select  id
            ,name
            ,'文科一班' as clazz
    from students
    where clazz = '文科一班'
) a
on t1.id = a.id
order by t1.sum_score desc
limit 10;

二、Hive建表语句

#EXTERNAL:外部的
#定义表名
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, ...) 
   
  #设置排序字段 升序、降序
  #num_buckets BUCKETS:桶的数量,通过hash取余获得桶的数量=Reduce的任务数量
  [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
  
  [
  	#指定设置行、列分隔符
    #行分隔符一般不指定,默认换行符/n分隔;列分隔符需要我们手动指定
   [ROW FORMAT row_format]
      
   #指定Hive储存格式:textFile、rcFile、SequenceFile 
   #如果不指定,默认为:textFile
   [STORED AS file_format]
  ]
  
  #指定储存位置
  #如果是外部表,必须加上location;如果是内部表,可加可不加(一般不加)
  [LOCATION hdfs_path]
  #跟外部表配合使用,比如:映射HBase表,然后可以使用HQL对hbase数据进行查询,当然速度比较慢
  [TBLPROPERTIES (property_name=property_value, ...)]  (Note:  only available starting with 0.6.0)
  [AS select_statement]  (Note: this feature is only available starting with 0.5.0.)
建表1:全部使用默认建表方式
create table students
(
    id bigint,
    name string,
    age int,
    gender string,
    clazz string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','; #必选,指定列分隔符 
建表2:指定location (这种方式也比较常用)
create table students2
(
    id bigint,
    name string,
    age int,
    gender string,
    clazz string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION '/input1'; 
#指定Hive表的数据的存储位置,一般在数据已经上传到HDFS,想要直接使用,会指定Location,通常Locaion会跟外部表一起使用,内部表有自己默认的location
建表3:指定存储格式
create table students3
(
    id bigint,
    name string,
    age int,
    gender string,
    clazz string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS rcfile; #指定储存格式为rcfile,inputFormat:RCFileInputFormat,outputFormat:RCFileOutputFormat,如果不指定,默认为textfile,注意:除textfile以外,其他的存储格式的数据都不能直接加载,需要使用从表加载的方式。
建表4:create table xxxx as select_statement(SQL语句) (这种方式比较常用)
#将select * from students2的输出结果作为数据,构建表students4,用as连接
#构建出来的表有数据,并且和select * from students2输出结果保持一致
create table students4 as select * from students2;
建表5:create table xxxx like table_name 只想建表,不需要加载数据
#构建与表students结构一样的表,构建出来的表没有数据,用like连接
create table students5 like students;

三、Hive 内部表(Managed tables)vs 外部表(External tables)

建表:
#创建内部表
create table students_internal
(
    id bigint,
    name string,
    age int,
    gender string,
    clazz string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','    #分隔符语句(数据以逗号分隔开)
LOCATION '/input2';	#手动指定该内部表表格创建在HDFS下的/input2目录内

#创建外部表,比内部表多了一个external
create external table students_external
(
    id bigint,
    name string,
    age int,
    gender string,
    clazz string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','	#分隔符语句(数据以逗号分隔开)
LOCATION '/input3';#手动指定该外部表表格创建在HDFS下的/input3目录内
(1)通常创建的表都属于内部表,不指定location,在哪个库创建的表,
对应的HDFS中的目录中,会显示对应表名的目录;
(2)如果在创建内部表的时候加上了location,例如LOCATION '/input2',
那么此表是创建在了HDFS的input2目录中,进入input3目录并不会看到此表名;
进入HDFS的/input2,这个页面就相当于是这个表
(3)在创建外部表的时候,必须要指定location,例如LOCATION '/input3',
同样的,外部表创建在了HDFS的input3目录中,进入input3目录并不会看到此表名;
进入HDFS的/input2,这个页面就相当于是这个外部表
加载数据(上传数据到HDFS):
#上传到内部表(数据会默认导入/input2/目录下的students_internal表)
hive> dfs -put /usr/local/soft/data/students.txt /input2/;

#上传到外部表(数据会默认导入/input3/目录下的students_external表)
hive> dfs -put /usr/local/soft/data/students.txt /input3/;
#创建外部表后,在HDFS中并不会看到表名,但实际是存在的
删除表:
hive> drop table students_internal;
Moved: 'hdfs://master:9000/input2' to trash at: hdfs://master:9000/user/root/.Trash/Current
OK
Time taken: 0.474 seconds
#在删除内部表的时候,会提示放入了回收站里

hive> drop table students_external;
OK
Time taken: 0.09 seconds
hive> 
#在删除外部表的时候,并会提示放入了回收站
删除内部表的时候,表中的数据(HDFS上的文件)会被同表的元数据一起删除;
(/input2、表名、上传的students.txt数据文件都被删除掉了)

删除外部表的时候,只会删除表的元数据,不会删除表中的数据(HDFS上的文件)
(/input3、上传的students.txt数据文件还在,表名没了)

一般在公司中,使用外部表多一点,因为数据可以需要被多个程序使用,避免误删,通常外部表会结合location一起使用

外部表还可以将其他数据源中的数据 映射到 hive中,比如说:hbase,ElasticSearch......

设计外部表的初衷就是 让表的元数据 与 数据 解耦(分隔开)

四、Hive加载数据

1、使用hdfs dfs -put 本地数据的路径 hive表对应的HDFS目录下;
2、使用 load data inpath 'hive表对应的HDFS目录下表的数据' into table 表名;

直接指定一张表,不需要指定表的路径,在加载数据的时候让它自己寻找目录存放进去

下列命令需要在hive shell里执行

#将HDFS上的students表下面的数据加载到students2表中
#此处的加载数据,属于移动数据,相当于剪切数据,加载之后,students表内的数据为空了
load data inpath '/user/hive/warehouse/test1.db/students/student.txt' into table students2;
#加上local关键字可以将Linux本地目录下的文件加载到hive表对应HDFS目录下,原文件不会被删除
load data local inpath '/usr/local/soft/data/student.txt' into table students;

#overwrite 覆盖加载
load data local inpath '/usr/local/soft/data/student.txt' overwrite into table students;
3、create table 表名 as SQL语句,也相当于一种加载方式
#将select * from students2的输出结果作为数据加载到表students4中,用as连接(相当于复制)
#students4为新创建的表
create table students4 as select * from students2;
4、insert into table 表名 SQL语句 (没有as)
#将select * from students的输出结果作为数据加载到表students2中(相当于复制)
insert into table students2 select * from students;

#覆盖插入 把into 换成 overwrite
#将select * from students的输出结果作为数据加载到表students2中(相当于覆盖)
insert overwrite table students2 select * from students;


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM