数据仓库-Hive

1.数据仓库的基本概念

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v0OhlHVi-1616598779764)(…/TypoarWrokPath/images/1615604642904.png)]

数据仓库的特性

数据仓库是面向主题的(Subject-Oriented )、集成的(Integrated)非易失的(Non-Volatile)和时变的(Time-Variant )数据集合,用以支持管理决策。

1.2.1. 面向主题

数据仓库是面向主题的,数据仓库通过一个个主题域将多个业务系统的数据加载到一起,为了各个主题(如:用户、订单、商品等)进行分析而建,操作型数据库是为了支撑各种业务而建立。

1.2.2. 集成性

数据仓库会将不同源数据库中的数据汇总到一起,数据仓库中的综合数据不能从原有的数据库系统直接得到。因此在数据进入数据仓库之前,必然要经过统一与整合,这一步是数据仓库建设中最关键、最复杂的一步(ETL),要统一源数据中所有矛盾之处,如字段的同名异义、异名同义、单位不统一、字长不一致,等等。

1.2.3. 非易失性

操作型数据库主要服务于日常的业务操作,使得数据库需要不断地对数据实时更新,以便迅速获得当前最新数据,不至于影响正常的业务运作。在数据仓库中只要保存过去的业务数据,不需要每一笔业务都实时更新数据仓库,而是根据商业需要每隔一段时间把一批较新的数据导入数据仓库。 数据仓库的数据反映的是一段相当长的时间内历史数据的内容,是不同时点的数据库的集合,以及基于这些快照进行统计、综合和重组的导出数据。数据仓库中的数据一般仅执行查询操作,很少会有删除和更新。但是需定期加载和刷新数据。

1.2.4. 时变性

数据仓库包含各种粒度的历史数据。数据仓库中的数据可能与某个特定日期、星期、月份、季度或者年份有关。数据仓库的目的是通过分析企业过去一段时间业务的经营状况,挖掘其中隐藏的模式。虽然数据仓库的用户不能修改数据,但并不是说数据仓库的数据是永远不变的。分析的结果只能反映过去的情况,当业务变化后,挖掘出的模式会失去时效性。因此数据仓库的数据需要定时更新,以适应决策的需要

2数据库与数据仓库的区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lmCOsEPg-1616598779768)(…/TypoarWrokPath/images/1615605202339.png)]

3. 数仓的分层架构

数据仓库的数据来源于不同的源数据,并提供多样的数据应用,数据自下而上流入数据仓库后向上层开放应用,而数据仓库只是中间集成化数据管理的一个平台。

源数据层(ODS)`:

​ 此层数据无任何更改,直接沿用外围系统数据结构和数据,不对外开放;为临时存储层,是接口数据的临时存储区域,为后一步的数据处理做准备。

数据仓库层(DW)`:

​ 也称为细节层,DW层的数据应该是一致的、准确的、干净的数据,即对源系统数据进行了清洗(去除了杂质)后的数据。

数据应用层(DA或APP)`:

​ 前端应用直接读取的数据源;根据报表、专题分析需求而计算生成的数据。

数据仓库从各数据源获取数据及在数据仓库内的数据转换和流动都可以认为是ETL(抽取Extra, 转化Transfer, 装载Load)的过程,ETL是数据仓库的流水线,也可以认为是数据仓库的血液,它维系着数据仓库中数据的新陈代谢,而数据仓库日常的管理和维护工作的大部分精力就是保持ETL的正常和稳定。

为什么要对数据仓库分层?

用空间换时间,通过大量的预处理来提升应用系统的用户体验(效率),因此数据仓库会存在大量冗余的数据;不分层的话,如果源业务系统的业务规则发生变化将会影响整个数据清洗过程,工作量巨大。

通过数据分层管理可以简化数据清洗的过程,因为把原来一步的工作分到了多个步骤去完成,相当于把一个复杂的工作拆成了多个简单的工作,把一个大的黑盒变成了一个白盒,每一层的处理逻辑都相对简单和容易理解,这样我们比较容易保证每一个步骤的正确性,当数据发生错误的时候,往往我们只需要局部调整某个步骤即可。

数仓的元数据管理

元数据(Meta Date),主要记录数据仓库中模型的定义、各层级间的映射关系、监控数据仓库的数据状态及ETL的任务运行状态。一般会通过元数据资料库(Metadata Repository)来统一地存储和管理元数据,其主要目的是使数据仓库的设计、部署、操作和管理能达成协同和一致。

元数据是数据仓库管理系统的重要组成部分,元数据管理是企业级数据仓库中的关键组件,贯穿数据仓库构建的整个过程,直接影响着数据仓库的构建、使用和维护。

构建数据仓库的主要步骤之一是ETL。这时元数据将发挥重要的作用,它定义了源数据系统到数据仓库的映射、数据转换的规则、数据仓库的逻辑结构、数据更新的规则、数据导入历史记录以及装载周期等相关内容。数据抽取和转换的专家以及数据仓库管理员正是通过元数据高效地构建数据仓库。

  • 用户在使用数据仓库时,通过元数据访问数据,明确数据项的含义以及定制报表。
  • 数据仓库的规模及其复杂性离不开正确的元数据管理,包括增加或移除外部数据源,改变数据清洗方法,控制出错的查询以及安排备份等。

元数据可分为技术元数据和业务元数据。技术元数据为开发和管理数据仓库的IT 人员使用,它描述了与数据仓库开发、管理和维护相关的数据,包括数据源信息、数据转换描述、数据仓库模型、数据清洗与更新规则、数据映射和访问权限等。而业务元数据为管理层和业务分析人员服务,从业务角度描述数据,包括商务术语、数据仓库中有什么数据、数据的位置和数据的可用性等,帮助业务人员更好地理解数据仓库中哪些数据是可用的以及如何使用。

由上可见,元数据不仅定义了数据仓库中数据的模式、来源、抽取和转换规则等,而且是整个数据仓库系统运行的基础,元数据把数据仓库系统中各个松散的组件联系起来,组成了一个有机的整体。

Hive的基本概念

什么是 Hive

Hive是基于Hadoop的一个数据仓库工具,可以将****结构化的数据****文件映射为一张数据库表,并提供类SQL查询功能。其本质是将SQL转换为MapReduce的任务进行运算,底层由HDFS来提供数据的存储,说白了hive可以理解为一个将SQL转换为MapReduce的任务的工具,甚至更进一步可以说hive就是一个MapReduce的客户端

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tvSdHLGv-1616598779771)(…/TypoarWrokPath/images/1615646634160.png)]

为什么使用 Hive

1.采用类SQL语法去操作数据,提供快速开发的能力。

2.避免了去写MapReduce,减少开发人员的学习成本。

3.功能扩展很方便。

Hive的架构

用户接口

包括CLI、JDBC/ODBC、WebGUI。其中,CLI(command line interface)为shell命令行;JDBC/ODBC是Hive的JAVA实现,与传统数据库JDBC类似;WebGUI是通过浏览器访问Hive。

元数据存储

通常是存储在关系数据库如mysql/derby中。Hive 将元数据存储在数据库中。Hive 中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。

解释器、编译器、优化器、执行器:

完成HQL 查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在HDFS 中,并在随后有MapReduce 调用执行。

5.查看日志方法

进入到日志的目录里面,使用命令 tail -f hive.log

6.HIVE的sql执行原理

是通过sql语句去解析元数据,根据元数据找到HDFS的路径,找到对应的内容

select * from test :在hive中的解释;from 就会先去找元数据如果存在就会通过元数据提供的路径到HDFS的路径,然后把把表名拼接上去,就形成了一个完整的hdfs路径,就可以在hdfs中找到对应的内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H4EDchAG-1616598779773)(…/TypoarWrokPath/images/1615734204375.png)]

7.使用jdbc连接

都要在hive目录下执行

1.开启metastore

bin/hive --service metastore

2.开启hiveserver2

bin/hive --service hiveserver2

3.连接jdbc

bin/beeline -u jdbc:hive2://hadoop102:10000 -n atguigu

8.执行报错bin/beeline -u jdbc:hive2://hadoop102:10000 -n atguigu

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dNG6E87k-1616598779775)(…/TypoarWrokPath/images/1615740629757.png)]

解决方案在hadoop 的etc下面hadoop的coer.site.xml中加入如下配置

atguigu根据你自己的用户组来定

hadoop.proxyuser.atguigu.hosts *

    hadoop.proxyuser.atguigu.groups
     *

9.日志位置

cd/tmp/atguigu tail -f hive 实时监控日志

10.查看进程

1.查看元数据服务进程

-v 表示不包含grep自己

ps -ef |grep -v grep |grep -i HiveMetastore

2.获取端口号

awk 表示根据空格进行拆分

$2 代表下标为二的

ps -ef |grep -v grep |grep -i HiveMetastore |awk ‘{print $2}’

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uer9VxWW-1616598779776)(…/TypoarWrokPath/images/1615743414567.png)]

11.解决中文乱码问题

# 创建表(row format delimited fields terminated by '\t')插入数据格式以'\t'分隔
create table teacher(t_id string,t_name string) row format delimited fields terminated by '\t'
create table course(c_id string,c_course string,t_id string) row format delimited fields terminated by '\t'
create table score(s_id string,c_id string,s_score string) row format delimited fields terminated by '\t'
create table student(s_id string,s_name string,s_birth date,s_sex string) row format delimited fields terminated by '\t'
# 以这种方式导入数据不会导致中文乱码  插入对应格式数据 'hdfs://用户名:8020/路径+文件名' 插入完成文件会丢失
LOAD DATA INPATH 'hdfs://singlenode:8020/Hive/school/teacher.txt' INTO TABLE teacher;

12.操作集合类型案列

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XJm0UCDw-1616598779778)(…/TypoarWrokPath/images/1615833288281.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lx30Uep0-1616598779778)(…/TypoarWrokPath/images/1615833308561.png)]

1案列操作

//(1)假设某表有如下一行,我们用 JSON 格式来表示其数据结构。在 Hive 下访问的格式为
{
 "name": "songsong",
 "friends": ["bingbing" , "lili"] , //列表 Array, 
 "children": { //键值 Map,
 "xiao song": 18 ,
 "xiaoxiao song": 19
 }
 "address": { //结构 Struct,
 "street": "hui long guan",
 "city": "beijing"
 } }
//创建本地测试文件 test.txt 上传到hdsf文件系统中 路径/user/hive/warehouse/mydata.db/test01
songsong,bingbing_lili,xiao song:18_xiaoxiao song:19,hui long guan_beijing
yangyang,caicai_susu,xiao yang:18_xiaoxiao yang:19,chao yang_beijing
//创建表
create table test01(
	name string,
	friends array<string>,
	children map<string, int>,
	address struct<street:string, city:string> )
	row format delimited fields terminated by ','  //列分隔符
	collection items terminated by '_'  //MAP STRUCT 和 ARRAY 的分隔符(数据分割符号)
	map keys terminated by ':'   //map内部分隔符
	lines terminated by '\n';   //行分隔符
//查询array集合 ,和java一样根据下标查询
select friends[0] from test01;
//查询map键值对
select children['xiao song']  from test01;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z7JIetB0-1616598779779)(…/TypoarWrokPath/images/1615833636777.png)]

13.hive的外部表和内部表

1.外部表和内部表区别

  1. 创建表时:创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径, 不对数据的位置做任何改变。
  2. 删除表时:在删除表的时候,内部表的元数据和数据会被一起删除, 而外部表只删除元数据,不删除数据。这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。
  3. hive默认创建的是内部表
  4. 外部表比内部表更加安全
  5. 在删除内部表的时候,Hive将会把属于表的元数据和数据全部删掉;而删除外部表的时候,Hive仅仅删除外部表的元数据,数据是不会删除的!
create external table employee(name string,work_place ARRAY<string>,sex_age STRUCT<sex:string,age:int>,skill_score MAP<string,int>,depart_title MAP<string,ARRAY<string>>)
    comment'这是一个员工表'row format delimited fields terminated by'|' 
    collection items terminated by',' 
    map keys terminated by ':' 
    stored as textfile location 'hdfs://singlenode132:8020/epm/employee';

14.数据导入\导出方式

1.使用本地文件插入表数据

load data local inpath ‘/opt/employee.txt’ into table employee; #以copy的方式导入数据

2.使用HDFS 的文件插入表数据

load data inpath ‘hdfs://sinlenode:8020/root/data/employee.txt’ into table emp.employee_ext; #没有local,使用hdfs上的mv命令导入数据

3.使用insert插入数据

insert overwrite table student_par select id, name from student where month=‘201709’;

insert into:以追加数据的方式插入到表或分区,原有数据不会删除

insert overwrite:会覆盖表中已存在的数据

注意:

Hive支持从同一个表进行多次插入

INSERT INTO中TABLE关键字是可选的

INSERT INTO可以指定插入到哪些字段中

如:INSERT INTO t(x,y,z)

INSERT INTO table_name VALUES,支持插入值列表

数据插入必须与指定列数相同

4.多表(多分区)插入模式(根据多张表查询结果)

from student 

 insert overwrite table student partition(month='201707')  

 select id, name where month='201709' 

 insert overwrite table student partition(month='201706') 

 select id, name where month='201709'; 

5.如果有分区的导入方式

-- LOCAL表示文件位于本地,OVERWRITE表示覆盖现有数据
LOAD DATA LOCAL INPATH '/home/dayongd/Downloads/employee.txt' 
OVERWRITE INTO TABLE employee_partitioned PARTITION (year=2014, month=12);

6.export / import

1.将表的数据到入到hdfs 上面

export table order_items02 To '/order/export' ; --路径必须不存在

2.将导出的数据导入到表的里面

import table o_01 from '/order/export'; --表名可以不存在 o_01是表名可以不存在

7.将hive数仓的数据导入到本地

--local 路径用本地的路径 overwrite表示覆盖原来的数据 
from order_items02 insert overwrite local directory '/opt/data/input/' select *;
--没有local 的就上传到hdfs中文件夹可以不存在
from order_items02 insert overwrite  directory '/opt/data/input/' select *;
--加了overwirte 覆盖
from order_items02 insert overwrite table order_itemstest  '/opt/data/input/' select *;

把值为null 的列放到最前面

--在使用left join(任何一种join只要有空值的时候就可以)的时候将列为null的放到最前面 order by asc升序
select * from customers cus left join orders ord on cus.customer_id=ord.customer_id order by order_id limit 30;

把值为null 的列放到最后面

--在使用left join(任何一种join只要有空值的时候就可以)的时候将列为null的放到最前面 order by desc升序
select * from customers cus left join orders ord on cus.customer_id=ord.customer_id order by order_id desc;

15.删除包含有的数据

2、 使用 cascade 关键字 drop database if exists 数据库名 cascade; 可以删除包含有表的数据库

3.数据出错恢复 truncate table bigdata3.student; 可以让索引回到1,清空所有的数据

4.HIVE高建表语句

1.CTAS – as select * from test 方式建表(会复制表结构和表数据)

2. 注:CTAS不能创建partition, external, bucket table

3.Like (只复制表结构,不复制表数据)

create table employee_like like employee;

16.union all 和 union 的区别

union和union all的区别是,union会自动压缩多个结果集合中的重复结果,而union all则将所有的结果全部显示出来,不管是不是重复。

Union:(两张表的字段必须要是一样的)对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;
UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。

实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION

Union All:对两个结果集进行并集操作,包括重复行,不进行排序;
如果返回的两个结果集中有重复的数据,那么返回的结果集就会包含重复的数据了

注意:如果数据本身不存在重复数据 ,使用 union ,union all ,使用union all 的效率更高

select stu.*,c1.c_course,c1.s_score  from school.student stu
,(select s_id,c_course,s_score from school.score s1,school.course cou  where cou.c_id =1 and s1.c_id = cou.c_id )  c1
,(select s_id,s_score from school.score s2 ,school.course cou where cou.c_id =2 and s2.c_id = cou.c_id)   c2
where c1.s_id in (c2.s_id) and c1.s_score >c2.s_score  and c1.s_id in (stu.s_id);  

17.使用WITH查询

WITH
      c1 AS (select  sco.s_id,sco.c_id,sco.s_score from school.score sco 
      ,school.course cou where sco.c_id='01' and sco.c_id = cou.c_id),
      c2 AS (select  sco.s_id,sco.c_id,sco.s_score from school.score sco
      ,school.course cou where sco.c_id='02' and sco.c_id = cou.c_id)
      select stu.*,cc1.s_score from school.student stu,c1 cc1 ,c2 cc2 where cc1.s_id in  (stu.s_id )         and cc1.s_id in (cc2.s_id) 
      and cc1.s_score > cc2.s_score

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JElVmCXv-1616598779781)(…/TypoarWrokPath/images/1615909392348.png)]

18.创建外部表 --external

1.要注意位置的顺序

create external table employee(name string,work_place ARRAY<string>,sex_age  STRUCT<sex:string,age:int>,skill_score MAP<string,int>,depart_title MAP<string,ARRAY<string>>)
    comment'这是一个员工表'row format delimited fields terminated by'|' --根据什么符号拆分
    collection items terminated by',' 
    map keys terminated by ':' 
    stored as textfile  --指定文件的类型
    tblproperties ('skip.header.line.count'='1'); --去掉文件中头部的N行数据,这里为1行
    location 'hdfs://singlenode132:8020/epm/employee';--指定外部表的存放位置

1.创建完表之后修改表不读取第一行

 alter table customer set tblproperties ('skip.header.line.count'='1'); --设定不读取数据中头部的N行数据,这里为1行 

19查看表结构

1.desc fromatted 表名

desc formatted employee;

20.查询数据库的详情

desc database 数据库名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QksQrMJJ-1616598779782)(…/TypoarWrokPath/images/1615911476633.png)]

21.建表语法

--创建内部表
create external table employee(name string,work_place ARRAY<string>,sex_age   STRUCT<sex:string,age:int>,skill_score MAP<string,int>,depart_title MAP<string,ARRAY<string>>)
    comment'这是一个员工表'
    row format delimited fields terminated by'|' --根据什么符号拆分
    collection items terminated by',' 
    map keys terminated by ':' 
    stored as textfile  --指定文件的类型
    tblproperties ('skip.header.line.count'='1'); --去掉文件中头部的N行数据,这里为1行
    location 'hdfs://singlenode132:8020/epm/employee';--指定外部表的存放位置

                               
   --创建内部表                       
  create  table employee(name string,work_place ARRAY<string>,sex_age  STRUCT<sex:string,age:int>,skill_score MAP<string,int>,depart_title MAP<string,ARRAY<string>>)
    comment'这是一个员工表' 
    row format delimited fields terminated by'|' --根据什么符号拆分
    collection items terminated by','      --集合使用什么隔开的
    map keys terminated by ':'           --map之间的隔开符
    stored as textfile  --指定文件的类型
    tblproperties ('skip.header.line.count'='1'); --去掉文件中头部的N行数据,这里为1行
  
  --使用 as select 建表
  create table 新表名 as select * from student;

1.建完表之后修改属性不读取第一行

​ alter table customer set tblproperties (‘skip.header.line.count’=‘1’); --设定不读取数据中头部的N行数据,这里为1行

22.内部表和外部表互相转换

1.alter table 表名 set tblproperties(‘EXTERNAL’=‘TRUE’); FALSE 为内部表 TRUE 为外部表

alter table test02 set tblproperties(‘EXTERNAL’=‘TRUE’);

23.自定义分割符

create table test03(id int,name string ) row format delimited fields terminated by ‘,’ ;

24.修改表名

1.alter table 旧表名 rename to 新表名;

alter table test03 rename to test04;

25.修改列名

  1. alter table 表名 change column 旧列名 新列名 新的数据类型; 如果旧列名是string类型的,就不能修改,因为string可以转换为很多类型

  2. 2.alter table 表名 replace columns(deptno string, dname string, loc string); 所有的列都会被替换

  3. 1alter table dept change column deptdesc desc string;

  4. 2alter table dept replace columns(deptno string, dname string, loc string);

26.添加列名

1.alter table 表名 add columns(新增列名 类型);

alter table dept add columns(deptdesc string);

27.添加分区

分区是指分文件夹

1.静态分区

开启动态分区参数设置

1.开启动态分区功能(默认 true,开启)
hive.exec.dynamic.partition=true
2.设置为非严格模式(动态分区的模式,默认 strict,表示必须指定至少一个分区为
nonstrict 模式表示允许所有的分区字段都可以使用动态分区。)
hive.exec.dynamic.partition.mode=nonstrict



--可以使用 load data inpath 'hdfs://sinlenode:8020/root/data/employee.txt' into table emp.employee_ext; 去添加数据
create table employee_partition(
 	  name string,
    work_place ARRAY<string>,
    sex_age STRUCT<sex:string,age:int>,
    skill_score MAP<string,int>,
    depart_tltie MAP<string,ARRAY<string>>
)
PARTITIONED BY (year int,month int)   --添加自定义分区
ROW FORMAT  DELIMITED FIELDS TERMINATED BY '|'
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';


--添加两个分区
alter table employee_partition add partition(year=2021,month=3) partition(year=2021,month=2);

--查看分区
show partitions employee_partition;

--删除分区
alter table employee_partition drop partition (year=2021,month =2)

--动态插入数据
--设置为动态分区
set hive.exec.dynamic.partition.mode=nonstrict
insert into table hive_demo.employee_partition
partition(year,month)
select * ,'2021' as year
,'3' as month
from hive_demo.employee;

hadoop 新增分区功能

--创建一张表指定分区一个字段 
create table dept_no_par2(dname string, loc string)
partitioned by (deptno int)  --指定分区列
 row format delimited fields terminated by ' ';
 --直接导入数据  指定分区列必须放到最后一列
insert into table dept_no_par2 select dname,loc,deptno from mydata.dept;

--创建一张表指定分区段两个字段
create table dept_no_par2(dname string, loc string)
partitioned by (deptno int,hour int)  --指定分区列
 row format delimited fields terminated by ' ';
 --直接导入数据  指定分区列必须放到最后一列
insert into table dept_no_par2 select dname,loc,deptno,hour from mydata.dept;
--注意会默认分区

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gjtdpUDQ-1616598779784)(…/TypoarWrokPath/images/1616516350956.png)]

2.动态分区

--不能使用 load data inpath 'hdfs://sinlenode:8020/root/data/employee.txt' into table emp.employee_ext; 去添加数据
--将employee_hr的所有数据都插入到employee_partitioned的表中

insert into table hive_demo.employee_partitioned partition(year,month) select name as name , num as num, phone as phone, shijian as shijian, year(shijian) as year ,month(shijian) as month from hive_demo.employee_hr;   


3.静态分区和动态分区的区别

1.静态分区需要手动去指定,而动态分区是基于查询参数的位置去推断分区的名称

2.静态分区的列是通过用户在编译时期传递过来的,而动态分区只有在sql执行时才能确定

28.添加分桶

1.创建分桶

create table stu_buck(id int, name string)
clustered by(id) 
into 4 buckets  --最好设置成-1 如果进行mr的时候只有两个job任务的话那么他就值分了两个桶
row format delimited fields terminated by ' ';


--导入数据
load data local inpath '/opt/module/data/stu.txt'  into table stu_buck;

分桶表操作需要注意的事项

(1)reduce 的个数设置为-1,让 Job 自行决定需要用多少个 reduce 或者将 reduce 的个

数设置为大于等于分桶表的桶数

(2)从 hdfs 中 load 数据到分桶表中,避免本地文件找不到问题

1.分桶对应于hdfs的文件

2.更高的查询处理

3.根据"桶列" 的哈希函数将数据进行分桶

4.分桶只有动态分桶 – SET hive.enforce.bucketing = true; 设置动态分桶

5.定义分桶

CLUSTERED BY (employee_id) INTO 2 BUCKETS —分桶的列必须是要表中已有的列

分桶数最好是2的n次方

29.分桶抽样

1.什么是分桶表

分桶是将数据集分解成更容易管理的若干部分的一个技术,是比表或分区更为细粒度的数据范围划分。针对某一列进行桶的组织,对列值哈希,然后除以桶的个数求余,决定将该条记录存放到哪个桶中。

2.总结

  1. 分桶对数据的处理比分区更加细粒度化;
  2. 分桶和分区两者不干扰,可以把分区表进一步分桶;
  3. 分区针对的是数据的存储路径;分桶针对的是数据文件。

1.随机抽样基于整行数据

--语法: TABLESAMPLE(BUCKET x OUT OF y)
--注意:x 的值必须小于等于 y 的值,否则
--FAILED: SemanticException [Error 10061]: Numerator should not be bigger 
--than denominator in sample clause for table stu_buck

--把数据分成32份 3表示从第三个桶往后找数据
SELECT * FROM table_name 
TABLESAMPLE(BUCKET 3 OUT OF 32 ON rand()) s;

2.随机抽样基于指定列(使用分桶列更高效)

SELECT * FROM table_name TABLESAMPLE(BUCKET 3 OUT OF 32 ON id) s;

3.随机抽样基于block suze

SELECT * FROM table_name TABLESAMPLE(10 PERCENT) s; --抽取百分之十
SELECT * FROM table_name TABLESAMPLE(1M) s;--抽取一兆
SELECT * FROM table_name TABLESAMPLE(10 rows) s; --抽取十行

30.正则表达式

--解释点 (.) 表示匹配除\n之外的其他任务字符串
--解释加(+) 表示匹配匹配前面的子字符串一次或则多次
SELECT `^o.*` FROM offers; --^ 表示以什么开头的 .*表示后面可以 有 或者 没有 数据
-- (.+y) 解释 表示在这个表达式前面一定要有其他的值 
select name,regexp(name,'^J.+y.+') as match from emp.employee_partition; --正则匹配name以J卡头,包含y的行,结果是true 、 false  


select name
,regexp(name,'.*ill.+') as Jy1 --必须有ill连在一起
,regexp(name,'.*[il12345678]+.+') as Jy2 --任选一个字符有出现
,regexp(name,'.*[i1l2345678]{3}.+') as Jy3 --任选3个字符连在一起出现
from emp.employee_partition ;


select name
,regexp(name,'^J.+y.+') as Jy
, regexp(work_place[0],'^T.+ron.+') as Tron --去匹配集合
from emp.employee_partition
where Jy==true ;


--选出包含name字段的列名,显示这些列的数据
--注意要先执行
SET hive.support.quoted.identifiers = none;
--才能使用
select `.*name.*` from emp.employee_ext;
--表示除了col_name1  col_name2  col_name3 的列其他全部查出来
select `(col_name1|col_name2| col_name3)?+.+`  from table;

--匹配多个列名
--方法1
SET hive.support.quoted.identifiers = none;
select `(.*id.*)|(.*name.*)` from customers;
--方法2
SET hive.support.quoted.identifiers = none;
select  `.*id.*`,`.*name.*`,`.*city.*` from customers limit 5; 
--方法3
select `(.*(id|name|city).*)` from customers;

31.虚拟列

hive 的虚拟列 主要有以下几个参数

INPUT__FILE__NAME --进行划分的输入文件名

BLOCK__OFFSET__INSIDE__FILE --文中的块内偏移量

ROW__OFFSET__INSIDE__BLOCK (默认不开启,需设置参数)–文件的行偏移量

注意 每个 __ 都是 两个下划线~

1.INPUT__FILE__NAME            --map任务读入File的全路径
select *, INPUT__FILE__NAME  from categories; 

2.BLOCK__OFFSET__INSIDE__FILE   --如果是RCFile或者是SequenceFile块压缩格式文件则显示Block file Offset,也就是当前快在文件的第一个字偏移量,如果是TextFile,显示当前行的第一个字节在文件中的偏移量
select *, BLOCK__OFFSET__INSIDE__FILE  from categories; 

3.ROW__OFFSET__INSIDE__BLOCK    --(默认不开启,需设置参数)
--RCFile和SequenceFile显示row number, 
--textfile显示为0
--注:若要显示ROW__OFFSET__INSIDE__BLOCK ,必须设置set hive.exec.rowoffset=true;
 set hive.exec.rowoffset=true; --设置
select *, ROW__OFFSET__INSIDE__BLOCK  from categories;

1.INPUT____FILE__NAME 结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ReOsRzWY-1616598779786)(…/TypoarWrokPath/images/1616083346140.png)]

2.BLOCK____OFFSET_____INSIDE______FILE结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CE2JAdrW-1616598779787)(…/TypoarWrokPath/images/1616083494422.png)]

3.ROW__OFFSET__INSIDE__BLOCK 结果

0表示是txt文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vZKJQgUE-1616598779788)(…/TypoarWrokPath/images/1616083989074.png)]

32.视图

1.使用视图的注意点

  • Hive中的试图,仅仅是一个sql语句的快捷方式
  • hive中的视图只是逻辑视图,没有物化视图
  • hive的视图,不支持增删改,只支持查询
  • hive的视图,只有的查询的时候,才会真正执行

2.创建视图

create view 新建视图名 as select * from 表名;

show views ; #只查看视图

desc formatted|extended 视图名 ;#查看视图的详细信息 formatted 查看全部信息 extended 是查看表结构

drop view 视图名; #删除视图

侧视图

1.创建侧视图

SELECT *,
       s_birth
FROM student LATERAL VIEW explode(split(s_birth,'-')) a AS s;
--  LATERAL VIEW explode(split(s_birth,'-')) 返回一个数组 变成列进行输出

--outer 即使output为空也会生成结果
SELECT *,s_birth
  FROM student LATERAL VIEW OUTER explode(split(null,'-')) a AS s;
  
 --支持多层级
select name,wps,skill,score from employee 
lateral view explode(work_place) work_place_single as wps
lateral view explode(skills_score) sks as skill,score;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gz2g59n5-1616598779790)(…/TypoarWrokPath/images/1616210901091.png)]

33.JOIN笔记

1.内连接 inner join

--内连接,只有进行连接的两个表中都存在与连接条件相匹配的数据才会被留下来
select * from score sco inner join student stu on sco.s_id=stu.s_id;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WVKQfle5-1616598779791)(…/TypoarWrokPath/images/1616206611766.png)]

2.左外连接 left join

--A left join  B 是以A表的记录为基础的,A可以看成左表,B可以看成右表,left join是以左表为准的.
     --意思说,左表(A)的记录将会全部表示出来(不管右边的表中是否存在与它们匹配的行),而右表(B)只会显示符合搜索条件的记录,比如符合on,where中的条件。B表记录不足的地方均为NULL.   A  left  join  B  等价B  right join   A 
  --(在数据库中成绩只有七个人,但是学生有八个) 
 
 select * from school.score  scr left join school.student  stu on scr.s_id= stu.s_id;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iLBiU3Dm-1616598779792)(…/TypoarWrokPath/images/1616208172898.png)]

3.右外连接 rigth join

--同理和left join相反,A right join B ,则显示B表中所有的记录,A表不足的用null填充
select * from score sco right join student stu on sco.s_id=stu.s_id;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g3YBRrJn-1616598779793)(…/TypoarWrokPath/images/1616207431665.png)]

4. full outer join 等价 full join ,全外连接

--包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行  在功能上,它等价于对这两个数据集合分别进行左外连接和右外连接,然后再使用消去重复行的并操作将上述两个结果集合并为一个结果集。

select * from score sco full join student stu on sco.s_id=stu.s_id;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XGmQFb4j-1616598779793)(…/TypoarWrokPath/images/1616208476647.png)]

6. left semi join 左半开连接 ,会显示左半边表中记录,前提是其记录对于右半边表满足于on语句中判定条件。

--只会显示左半边的表
select * from score sco left semi join student stu on sco.s_id=stu.s_id;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9rVAZGyb-1616598779795)(…/TypoarWrokPath/images/1616208655887.png)]

7.自连接是自身连接,指同一个表自己与自己进行连接。这种一元连接通常用于从自反关系(也称作递归关系)中抽取数据

select * from student stu inner join student stu1 on stu.s_id=stu1.s_id;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zYoUnmtj-1616598779795)(…/TypoarWrokPath/images/1616208844322.png)]

8.MAPJOIN

1. ,Hive中的Join可分为Common Join(Reduce阶段完成join)和Map Join(Map阶段完成join)

2.开启join操作

set hive.auto.convert.join = true(默认值)

运行时自动将连接转换为MAPJOIN

MAPJOIN操作不支持:

1.在UNION ALL, LATERAL VIEW, GROUP BY/JOIN/SORT

BY/CLUSTER BY/DISTRIBUTE BY等操作后面

在UNION, JOIN 以及其他 MAPJOIN之前

34.排序

-执行的先后顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nQXlgyAh-1616598779797)(…/TypoarWrokPath/images/1616490147382.png)]

1.order by

全局排序 desc 降序 asc 升序 效率低

注意:使用 order by 全局只有一个reduce

每个 Reduce内部排序(Sort By)

Sort By:对于大规模的数据集 order by 的效率非常低。在很多情况下,并不需要全局排

序,此时可以使用 sort by

Sort by 为每个 reducer 产生一个排序文件。每个 Reducer 内部进行排序,对全局结果集

来说不是排序。

1**)设置 reduce 个数

<font color='cornflowerblue'>hive (default)> set mapreduce.job.reduces=3; </font>

2**)查看设置** reduce 个数

<font color='cornflowerblue'>hive (default)> set mapreduce.job.reduces; </font>

3**)根据部门编号降序查看员工信息**

<font color='cornflowerblue'>hive (default)> select * from emp sort by deptno desc; </font>

4**)将查询结果导入到文件中(按照部门编号降序排序)**

hive (default)> insert overwrite local directory  

'/opt/module/data/sortby-result'  --路径不能存在

select * from emp sort by deptno desc;  -会在对应的文件夹下面产生对应的文件个数

分区(Distribute By)

Distribute By: 在有些情况下,我们需要控制某个特定行应该到哪个 reducer,通常是为

了进行后续的聚集操作。distribute by 子句可以做这件事。distribute by 类似 MR 中 partition

(自定义分区),进行分区,结合 sort by 使用。

对于 distribute by 进行测试,一定要分配多 reduce 进行处理,否则无法看到 distribute

by 的效果。

案例实操:

(1)先按照部门编号分区,再按照员工编号降序排序。

hive (default)> set mapreduce.job.reduces=3;

hive (default)> insert overwrite local directory

‘/opt/module/data/distribute-result’ select * from emp distribute by

deptno sort by empno desc;

注意:

distribute by 的分区规则是根据分区字段的 hash 码与 reduce 的个数进行模除后,

余数相同的分到一个区。

Hive 要求 DISTRIBUTE BY 语句要写在 SORT BY 语句之前。

6.4.6 Cluster By

当 distribute by 和 sorts by 字段相同时,可以使用 cluster by 方式。

cluster by 除了具有 distribute by 的功能外还兼具 sort by 的功能。但是排序只能是升序

排序,不能指定排序规则为 ASC 或者 DESC。

(1)以下两种写法等价

hive (default)> select * from emp cluster by deptno;

hive (default)> select * from emp distribute by deptno sort by deptno;

注意:按照部门编号分区,不一定就是固定死的数值,可以是 20 号和 30 号部门分到一

个分区里面去 有数据倾斜的现象

1.rank() over()

--成绩相同的,并列名次,下一个名次空出被占用的名次
select name
,course
,score
,rank() over (partition by course order by score desc) rank
from student ;
--注意: 使用rank() over的时候,空值是最大的,如果排序字段为null,可能造成null字段排在最前面,影响排序结果。可以这样:rank() over(partition by course order by score desc nulls last)来规避这个问题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ByiMMNHf-1616598779798)(…/TypoarWrokPath/images/1616401421823.png)]

2.dense_rank() over()


--成绩相同的,并列名次,下一个名次不空出被占用的名次
select name
,course
,score
,dense_rank() over (partition by course order by score desc) rank

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z3mno65B-1616598779801)(…/TypoarWrokPath/images/1616402138545.png)]

3.row_number over

--不管是否并列,都进行连续排名
select name
,course
,score
,row_number() over(partition by course order by score desc) 
from student ;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Yq8YRFl-1616598779802)(…/TypoarWrokPath/images/1616402688507.png)]

35.cast when 和 i f


--case when  then  else end 语法
--case sex when '男'  then 1 else 0 end 
--解释 当sex的值等于男的时候就是1 否则就是0 end 就是退出
select  dept_id,sum(case sex when '男'  then 1 else 0 end)  nan,sum(case sex when  '女'  then 1 else 0 end)  nv from  emp_sex group by dept_id;

--多条件判断
select  dept_id,sum(case sex when '男'  then 1 when '男'  then 1 when '男'  then 1 when '男'  then 1 else 0 end)  nan,sum(case sex when  '女'  then 1 else 0 end)  nv from  emp_sex group by dept_id;

--if判断 跟java的意思一样的
--if(sex='男',1,0) 解释 如果sex的值是男的就返回一,否则就返回0
select  dept_id,sum(if(sex='男',1,0))  nan,sum(if(sex='女',1,0))  nv from  emp_sex group by dept_id;

SQL练习

--1.创建数据库
create database school_qe;

--创建课程表
create table  COURSE
(`CNO`      string  comment '课程编号',
`CNAME`     string   comment '课程名称,',
`TNO`       string     comment '教师编号'
)
row format delimited fields terminated by ',' ;
--导入数据
load data local inpath '/opt/data/COURSE.txt' into table  course; 



--创建成绩表
create table  SCORE
(`SNO`      string  comment '学生编号',
`CNO`       string  comment '课程编号',
`DEGREE`    int  comment '分数'
)
row format delimited fields terminated by ',' ;
load data local inpath '/opt/data/SCORE.txt' into table  SCORE; 

--创建学生表
create table  Student
(`SNO`      string  comment '学生编号',
`SNAME`     string  comment '学生姓名',
`SSEX`      string     comment '学生性别',
`SBIRTHDAY` string     comment '出生年月',
`CLASS` string     comment '班级'
)
row format delimited fields terminated by ',' ;
load data local inpath '/opt/data/STUDENT.txt' into table  Student; 


--创建老师表
 create table  TEACHER
(`TNO`      string  comment '教师编号',
`TNAME`     string  comment '教师姓名',
`TSEX`      string     comment '性别',
`TBIRTHDAY` string     comment '出生年月',
`PROF` string     comment '职称',
`DEPART` string     comment '课程'
)row format delimited fields terminated by ',' ;
load data local inpath '/opt/data/TEACHER.txt' into table  TEACHER; 


--2.练习
--1、查询Score表中成绩在60到80之间的所有记录
select *  from score where degree between 60 and 80;
--2、查询Score表中成绩为85,86或88的记录
select * from score where degree in(85,86,88);
--3、以Cno升序、Degree降序查询Score表的所有记录。
select * from score order by cno asc,degree desc;
--4、查询Score表中的最高分的学生学号和课程号。
--1.第一种方式 使用order by 进行分组
SELECT a.sno,a.cno  from (
SELECT * FROM score ORDER BY degree DESC LIMIT 1
) a ;  
--第二种方式 使用 sort by 进行排序
select a.sno,a.cno from (
select * from score sort by degree desc limit 1
) a ;
--5、查询Score表中至少有5名学生选修的并以3开头的课程的平均分数。
  select cno,avg(degree) from score
  where cno like'%3%'
  group by cno
  having count(cno) >=5;
--6、查询最低分大于70,最高分小于90的Sno列。
SELECT sno  FROM score
GROUP BY sno
HAVING min(degree) >70 and max(degree)<90
--7、查询所有学生的Sname、Cno和Degree列
SELECT stu.sname,sco.degree,sco.cno FROM score sco JOIN student stu  on  sco.sno = stu.sno 
--8、查询“95033”班所选课程的平均分。
with 
  s_is as (select sno from student where class ='95033')
  select avg(sco.degree) from score sco ,s_is ss where sco.sno in(ss.sno) ;

基金sql题目

create table jijin(
 jijin_code string,
 jijin_time string,
 jijin_bcode string
)
row format delimited fields terminated by ',' ;

load data local inpath '/opt/data/jijin.txt' into table  jijin; 

36.聚合运算

1.GROUP BY用于分组

Hive基本内置聚合函数与GROUP BY一起使用

如果没有指定GROUP BY子句,则默认聚合整个表

除聚合函数外,所选的其他列也必须包含在GROUP BY中

GROUP BY支持使用CASE WHEN或表达式

支持按位置编号分组

set hive.groupby.orderby.position.alias=true;

Hive****聚合运算 - GROUP BY

select category, max(offervalue) from offers group by category;

– group by使用表达式

select if(category > 4000, ‘GOOD’, ‘BAD’) as newcat,max(offervalue)

from offers group by category if(category > 4000, ‘GOOD’, ‘BAD’);

解释: 如果 category 大于4000 就是GOOD 否则就是 BAD group by 根据if 里面的判断 大于4000 就根据GOOD进行

分组,小于4000就根据BAD 进行分组

2.Hive聚合运算 - HAVING

HAVING:对GROUP BY聚合结果的条件过滤

可以避免在GROUP BY之后使用子查询

HAVING之后可以使用表达式,不建议

--having使用
select sex_age.age from employee group by sex_age.age having count(*) <= 1;
--使用子查询代替having 不建议使用
select a.age from ( select count(*) as cnt, sex_age.age 
from employee group by sex_age.age ) a where a.cnt <= 1;

模拟面试:having 和 where有什么不同?

having 和where 都是进行筛选的,

但是having 是对于 分组之后的数据进行删除, having 一定要和 group by 一起使用 但是group by 可以单独使用

而 其他筛选就使用 where 进行筛选

37.窗口函数

1.窗口函数是一组特殊函数

扫描多个输入行来计算每个输出值,为每行数据生成一行结果

可以通过窗口函数来实现复杂的计算和聚合

38.函数

函数三大类型

1.UDF:一进一出

2.UDAF:多进一出

3.UDTF:一进多出

解释:一和多指的是输入数据的行数

1.系统内置函数

查看系统自带的函数

 show functions; 

显示自带的函数的用法

desc function upper; 

详细显示自带的函数的用法

 desc function extended upper;

2.空字段赋值

函数说明

NVL:给值为 NULL 的数据赋值,它的格式是 NVL( value,default_value)。它的功能是如

果 value 为 NULL,则 NVL 函数返回 default_value 的值,否则返回 value 的值,如果两个参数

都为 NULL ,则返回 NULL

--如果comm的这一列的值有空的就用-1来填充
select comm,nvl(comm, -1) from emp;

3.小案列

1.准备数据

悟空 A 男
大海 A 男
宋宋 B 男
凤姐 A 女
婷姐 B 女
婷婷 B 女

2.需求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2PubwnW1-1616598779803)(…/TypoarWrokPath/images/1616596401989.png)]

3.步骤


select
 dept_id,
 sum(case sex when '男' then 1 else 0 end) male_count, --使用if进行判断,然后进行累加
 sum(case sex when '女' then 1 else 0 end) female_count --使用if进行判断,然后进行累加
from emp_sex 
group by dept_id;  --对部门进行分组

re 都是进行筛选的,

但是having 是对于 分组之后的数据进行删除, having 一定要和 group by 一起使用 但是group by 可以单独使用

而 其他筛选就使用 where 进行筛选

37.窗口函数

1.窗口函数是一组特殊函数

扫描多个输入行来计算每个输出值,为每行数据生成一行结果

可以通过窗口函数来实现复杂的计算和聚合

38.函数

函数三大类型

1.UDF:一进一出

2.UDAF:多进一出

3.UDTF:一进多出

解释:一和多指的是输入数据的行数

1.系统内置函数

查看系统自带的函数

 show functions; 

显示自带的函数的用法

desc function upper; 

详细显示自带的函数的用法

 desc function extended upper;

2.空字段赋值

函数说明

NVL:给值为 NULL 的数据赋值,它的格式是 NVL( value,default_value)。它的功能是如

果 value 为 NULL,则 NVL 函数返回 default_value 的值,否则返回 value 的值,如果两个参数

都为 NULL ,则返回 NULL

--如果comm的这一列的值有空的就用-1来填充
select comm,nvl(comm, -1) from emp;

3.小案列

1.准备数据

悟空 A 男
大海 A 男
宋宋 B 男
凤姐 A 女
婷姐 B 女
婷婷 B 女

2.需求

[外链图片转存中…(img-2PubwnW1-1616598779803)]

3.步骤


select
 dept_id,
 sum(case sex when '男' then 1 else 0 end) male_count, --使用if进行判断,然后进行累加
 sum(case sex when '女' then 1 else 0 end) female_count --使用if进行判断,然后进行累加
from emp_sex 
group by dept_id;  --对部门进行分组

你可能感兴趣的:(HIVE,hive总结,大数据,hive)