Hive的常见用法

一、创建表

1.1内部表

create table 数据库名.表名(
    属性(一般都用string类型)
)
row format delimited fields terminated by ','
stored as textfile -- 文本文件
stored as orc -- orc压缩文件,压缩后别人无法读取
stored as parquet -- 别人需要继续使用数据

1.2外部表

create external table 数据库名.表名(
    属性
)
row format delimited fields terminated by ','
location '/路径'  -- hdfs上的路径,需要提前创好,hdfs dfs -mkdir -P /路径

1.3 特殊类型的数据库

create external table 数据库名.表名(
    job ARRAY(string),
    sex_age STRUCT<sex:int,age:int>,
    skill MAP<string,string>
)
row format delimited fields terminated by ','
collect items terminated by '_'  -- 集合结束符
map keys terminated by ':'  -- map结束符
location '/路径'

1.4 csv作为数据源

create external table ...(
    属性
)
row format serde 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
with serdeproperties 
(
    'separatorChar' = ',',  -- 分隔符
    'quoteChar'     = '\"', -- 引号符
    'escapeChar'    = '\\'  -- 转义符
)
location '/路径'
tblproperties('skip.header.line.count'='1') --去除首行

1.5 根据已有表创建新表

1.5.1 CTAS  (mysql、oracle、hive都可以用)连数据一起复制

create table ... as select * from ...

1.5.2 like  (只有hive有)只复制表结构

create table ... like ...

1.6 创建临时表

create temporary table ...(
       ...
)
row format delimited fields terminated by ','

二、数据上传

2.1 外部表上传

load data local inpath '/opt/data/aa.txt' overwrite into table mydemo.test1 
-- local inpath表示Linux本地文件,不加表示hadoop处文件 、、overwrite起到先清空,再插入

压缩需注意:load加载数据不能转换 

hdfs dfs -put /opt/data/data.csv /tab1
-- 上传至hdfs

三、创建一个分区表

3.1 静态分区

-- 1.创建一个分区表
create table mydemo.my_part(
    id string,
    name string
)
partitioned by (birmonth string)
row format delimited fields terminated by ','

-- 2.手工创建一个静态分区
alter table mydemo.my_part add partition(birmonth='01') --手工添加一个文件夹

-- 3.塞数据
load data local inpath '/opt/data/aa.txt' overwrite into table 
mydemo.my_part partition(birmonth='01')

insert into mydemo.my_part partition(birmonth='01') select id,name from mydemo.usi

3.2 动态分区(根据某列值进行分区)

-- 1. 建立分区表
create table mydemo.my_part1(
    id string,
    name string
)
partitioned by (birmonth string)
row format delimited fields terminated by ','

-- 2. 动态分区插入数据
-- 动态分区是根据查询分区列的有几种变化就有几个分区(例如:月份)
-- 默认最大分区的个数为100个,可以修改最大分区个数 -- hive-site.xml
-- set hive.exec.max.dynamic.partitions=10000
-- set hive.exec.max.dynamic.partitions.pernode=10000

-- 动态插入前要设置分区属性
set hive.exec.dynamic.partition=true
set hive.exec.dynamic.partition.mode=nonstrict
insert into mydemo.my_part1 partition(birmonth) select id,name,
month(regexp_replace(bir,'/','-')) birmonth from mydemo.usi

四、分桶表 (一般用于抽样,根据hash值进行分区)

-- 1. 创建一个分桶表
create table mydemo.bck_user(
    id string,
    name string,
    gender string
)
clustered by(gender)  -- 对gender列进行排序
into 2 buckets        -- 分两个桶
row format delimited fields terminated by ','

-- 2. 设置执行为TRUE,两个reduce
set hive.enforce.bucketing=true
set mapreduce.job.reduces=2

-- 3.上传数据(一般创一个零时表,用于数据上传)
insert into table mydemo.bck_user select * from mydemo.tmp

-- 4. 
-- 分桶表抽样
-- 确定三个值 n=总桶数  x=抽桶的开始位置   y  2^z =抽取总桶数的比例  

select count(*) from mydemo.bck_user tablesample(bucket 1 out of 2 on gender)

select count(*) from mydemo.bck_user tablesample(10 percent) -- 按10%抽取 (普通表)

select count(*) from mydemo.bck_user tablesample(1K) -- 抽指定大小

五、视图

与oracle一样

六、侧视图

select id,name,bir,loc,ind 
from mydemo.usi 
lateral view posexplode(split(likes,',')) a 
as loc,ind

-- loc 序号  ind 每一个值
-- 相当于一列多个值,转为一个一个值

select id,name,bir,b
from mydemo.usi 
lateral view explode(split(likes,',')) a 
as b

-- spark
df1.select($"userid",explode(split($"friendid"," ")))

七、排序

7.1、order by

整体数据排序,所有数据在reduce集中到一个节点上排序

7.2、distribute by(可以升序降序)

本身不排序,是将数据进行分区,工作在mapper节点上,没有数据迁移,一般个sort by 配合使用,所以mapper节点排序,只能保证mapper节点,就是部分数据有序

7.3、cluster by(只能升序)

基本等于 distribute by + sort by 但是,cluster by 只能按一列进行排序

八、数据的导入导出

-- 导入
inport table .... from '/temp'  -- 地址为hdfs上

-- 导出
export table .... to '/temp'

九、多个值转为集合

collect_list()

collect_set()  不重复

十、窗口函数(重点)

over:将窗口中处理的数据和未处理的列进行笛卡尔积的匹配

① 前置函数(窗口中的数据如何计算)

lag (lag(列名,1,xxx)  这一列向下一行,第一行补xxx)               lead

row_number                rank                dense_rank        

sum         arg                count

② 内置函数

partition by 数据分区(窗口)

order by  排序(窗口内排序)

window子句

-- preceding:向前
-- following:向后
-- current row:当前行
-- unbounded:起点   
-- unbounded preceding:从起点开始  
-- unbounded following 到后面终点


select name,orderdate,cost,
    sum(cost) over(partition by name) usercountmoney,
    sum(cost) over(partition by name order by orderdate) addusermoney1,
    sum(cost) over(partition by name order by orderdate rows between unbounded preceding and current row) addusermoney2, -- 开始到当前行
    sum(cost) over(partition by name order by orderdate rows between 1 preceding and 1 following) abadd,  -- 前一行后一行相加
    sum(cost) over(partition by name order by orderdate rows between current row and unbounded following) lastadd
from exp2.orders

十、DML导入

1.load:作用将数据直接加载到表目录中
    语法:  load  data [local] inpath 'xx' [overwrite] into table 表名 partition()
    
                local:  如果导入的文件在本地文件系统,需要加上local,使用put将本地上传到hdfs
                          不加local默认导入的文件是在hdfs,使用mv将源文件移动到目标目录

2. insert:insert方式运行MR程序,通过程序将数据输出到表目录!
        在某些场景,必须使用insert方式来导入数据:
                ①向分桶表插入数据
                ②如果指定表中的数据,不是以纯文本形式存储,需要使用insert方式导入

    语法: insert into | overwrite table 表名 select xxx | values(),(),() 
                insert into: 向表中追加新的数据
                insert overwrite: 先清空表中所有的数据,再向表中添加新的数据
    特殊情况: 多插入模式(从一张源表查询,向多个目标表插入)
                from 源表
                insert xxxx  目标表  select xxx
                insert xxxx  目标表  select xxx
                insert xxxx  目标表  select xxx
    举例: from deptpart2
            insert into table deptpart1 partition(area='huaxi') select deptno,dname,loc
            insert into table deptpart1 partition(area='huaxinan') select deptno,dname,loc

3. location: 在建表时,指定表的location为数据存放的目录

4. import :  不仅可以导入数据还可以顺便导入元数据(表结构)。Import只能导入export输出的内容!
                
IMPORT [[EXTERNAL] TABLE 表名(新表或已经存在的表) [PARTITION (part_column="value"[, ...])]]
  FROM 'source_path'
  [LOCATION 'import_target_path']
                ①如果向一个新表中导入数据,hive会根据要导入表的元数据自动创建表
                ②如果向一个已经存在的表导入数据,在导入之前会先检查表的结构和属性是否一致
                        只有在表的结构和属性一致时,才会执行导入
                ③不管表是否为空,要导入的分区必须是不存在的
                
  import external table importtable1  from '/export1'

如果导入的是external外部表,那么这个表是不控制数据的生命周期的,换句话说就是只拷贝源表的结构而不拷贝数据,只作引用


十一、函数

1.查看函数
        函数有库的概念,系统提供的除外,系统提供的函数可以在任意库使用!
        查看当前库所有的函数:show functions;
        查看函数的使用: desc function 函数名
        查看函数的详细使用: desc function extended 函数名
        
2.函数的分类
        函数的来源:  

                      ①系统函数,自带的,直接使用即可
                      ②用户自定义的函数。
                            a)遵守hive函数类的要求,自定义一个函数类
                            b)打包函数,放入到hive的lib目录下,或在HIVE_HOME/auxlib
                                    auxlib用来存放hive可以加载的第三方jar包的目录
                            c)创建一个函数,让这个函数和之前编写的类关联
                                    函数有库的概念
                            d)使用函数
        
        函数按照特征分:  

        UDF:  用户定义的函数。 一进一出。 输入单个参数,返回单个结果!                          cast('a' as int) 返回 null
        UDTF:  用户定义的表生成函数。 一进多出。传入一个参数(集合类型),返回一个结果集!
        UDAF: 用户定义的聚集函数。 多进一出。 传入一列多行的数据,返回一个结果(一列一行)  count,avg,sum

11.1 UDF函数自定义:

11.1.1 java打包

1、pom包

<!-- https://mvnrepository.com/artifact/org.apache.hive/hive-exec -->
    <dependency>
      <groupId>org.apache.hive</groupId>
      <artifactId>hive-exec</artifactId>
      <version>1.1.0</version>
    </dependency>

    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-common</artifactId>
      <version>2.6.0</version>
    </dependency>


<!-- 整体打包 -->
<build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>com.ksf.myfunc.Quarte</mainClass><!--这里改成自己的主类位置-->
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

 2、函数

package com.ksf.myfunc;

import org.apache.hadoop.hive.ql.exec.UDF;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class Quarte extends UDF {

    public String evaluate(String time){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        try {
            Date date = sdf.parse(time);
            // 获取月份
            cal.setTime(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        int month = cal.get(Calendar.MONTH);
        // 根据月份计算季度
        if(month<3){
            return "一季度";
        }else if(month < 6){
            return "二季度";
        }else if (month< 9){
            return "三季度";
        }else {
            return "四季度";
        }
    }

    public static void main(String[] args) {
        Quarte q = new Quarte();
        System.out.println(q.evaluate("2021-09-24"));
    }
}

3. 上传至Linux文件

  1.  add jar /opt/myfunc-1.0-SNAPSHOT-jar-with-dependencies.jar   添加jar包
  2. create function exp2.quarte as 'com.ksf.myfunc.Quarte'   创建函数

11.2.1 宏函数

create temporary macro func_age(x string) case
when cast(x as int)<20 then '青年'
when cast(x as int)<30 then '中年'
when cast(x as int)<50 then '中老年'
else '老年'
end


十二、本地数据上传至Hive

1、pom包

<!-- 连接hive包 -->
    <!-- https://mvnrepository.com/artifact/org.apache.hive/hive-jdbc -->
    <dependency>
      <groupId>org.apache.hive</groupId>
      <artifactId>hive-jdbc</artifactId>
      <version>1.1.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-common</artifactId>
      <version>2.6.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-client -->
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>2.6.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs -->
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-hdfs</artifactId>
      <version>2.6.0</version>
    </dependency>

2.代码

package com.ksf.myhive.services;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.net.URI;
import java.sql.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class FileTimeData {

    /**
     * 建造批量数据
     */
    public List<String> buileData() {
        ArrayList<String> lst = new ArrayList<>();
        Calendar cal = Calendar.getInstance();
        cal.set(2017, 1, 1, 0, 0, 0);
        String sql = "%s,%s,%s,%s,%s,%s\n";
        for (int i = 0; i < 8783; i++) {
            cal.add(Calendar.HOUR, 1);
            String res = String.format(sql, (i + 1),
                    cal.get(Calendar.YEAR),
                    cal.get(Calendar.MONTH),
                    cal.get(Calendar.DATE),
                    calQuarter(cal.get(Calendar.MONTH)),
                    cal.get(Calendar.HOUR_OF_DAY));
            lst.add(res);
        }
        return lst;
    }

    /**
     *    上传至hdfs
     * @throws Exception
     */
    private void makeHDFSFile() throws Exception {
        System.setProperty("HADOOP_USER_NAME", "root");
        String path = "hdfs://192.168.56.160:9000/tmp1";
        FileSystem fs = FileSystem.get(new URI(path), new Configuration());
        if (fs.exists(new Path(path))) {
            fs.delete(new Path(path), true);
        }
        fs.mkdirs(new Path(path));
        // 创建文件
        FSDataOutputStream fos = fs.create(new Path("/tmp1/tmp.txt"));
        // 写入文件信息
        List<String> infos = buileData();
        for (String info : infos) {
            fos.write(info.getBytes());
        }
        fos.flush();
        fos.close();
    }

    /**
     * 插入数据至hive
     */
    public void loadData(){
        try {
            Class.forName("org.apache.hive.jdbc.HiveDriver");
            Connection conn =
                    DriverManager.getConnection("jdbc:hive2://192.168.56.160:10000/dws_sale",
                                                "root",
                                                "root");
            Statement stat = conn.createStatement();
            String sql = "load data inpath '/tmp1/tmp.txt' overwrite into table dws_sale.dws_time_dim";
            stat.execute(sql);
            conn.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    private int calQuarter(int month) {
        return (int) (Math.floor(month / 3) + 1);
    }

    public static void main(String[] args) throws Exception{
        FileTimeData ftd = new FileTimeData();
        ftd.makeHDFSFile(); // 建造数据
        ftd.loadData();  // 向表中加数据
    }
}

十三、数仓建设

1.ods层:就是元数据,创建ods数据库,存放数据

2.dwd层:《数据探索》

  1. -- 查看文件有多少行
    hdfs dfs -cat /sale/customer_details/customer_details.csv | wc -l
  2. 查看表格多少行
    select count(*) from ods_sale.ods_customers
  3. 查看有没有重复
    with    
    r1 as (select max(customer_id) from ods_sale.ods_customers group by customer_id)
    select count(*) from r1
  4. 查看名字有没有为空
    注:每列都需要验证,无问题创建新表,stored as orc

3. dws层

创建维度表!!! 

4. ads分析层

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值