hive数据仓库

数据仓库-Hive

数据仓库

1.1. 基本概念

英文名称为Data Warehouse,可简写为DW或DWH。数据仓库的目的是构建面向分析的集成化数据环境,为企业提供决策支持(Decision Support)。

数据仓库是存数据的,企业的各种数据往里面存,主要目的是为了分析有效数据,后续会基于它产出供分析挖掘的数据,或者数据应用需要的数据,如企业的分析性报告和各类报表等。

可以理解为:面向分析的存储系统

1.2. 主要特征

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

1.2.1. 面向主题

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

1.2.2. 集成性

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

1.2.3. 非易失性

操作型数据库主要服务于日常的业务操作,使得数据库需要不断地对数据实时更新,以便迅速获得当前最新数据,不至于影响正常的业务运作。

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

1.2.4. 时变性

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

1.3. 数据库与数据仓库的区别

数据库与数据仓库的区别实际讲的是 OLTPOLAP 的区别。

操作型处理,叫联机事务处理 OLTP(On-Line Transaction Processing,),也可以称面向交易的处理系统,它是针对具体业务在数据库联机的日常操作,通常对少数记录进行查询、修改。用户较为关心操作的响应时间、数据的安全性、完整性和并发支持的用户数等问题。传统的数据库系统作为数据管理的主要手段,主要用于操作型处理。

分析型处理,叫联机分析处理 OLAP(On-Line Analytical Processing)一般针对某些主题的历史数据进行分析,支持 管理决策。

首先要明白,数据仓库的出现,并不是要取代数据库。

  • 数据库是面向事务的设计,数据仓库是面向主题设计的。
  • 数据库一般存储业务数据,数据仓库存储的一般是历史数据。
  • 数据库设计是尽量避免冗余,一般针对某一业务应用进行设计,比如一张简单的User表,记录用户名、密码等简单数据即可,符合业务应用,但是不符合分析。数据仓库在设计是有意引入冗余,依照分析需求,分析维度、分析指标进行设计。
  • 数据库是为捕获数据而设计,数据仓库是为分析数据而设计。

数据仓库,是在数据库已经大量存在的情况下,为了进一步挖掘数据资源、为了决策需要而产生的,它决不是所谓的“大型数据库”。

1.4. 数仓的分层架构

按照数据流入流出的过程,数据仓库架构可分为三层——源数据、数据仓库、数据应用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XPs5FFUf-1647348827503)(http://ppw6n93dt.bkt.clouddn.com/d312300d6dcbf0a66412ad4ec422236d.png)]

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

  • 源数据层(ODS):此层数据无任何更改,直接沿用外围系统数据结构和数据,不对外开放;为临时存储层,是接口数据的临时存储区域,为后一步的数据处理做准备。
  • 数据仓库层(DW):也称为细节层,DW层的数据应该是一致的、准确的、干净的数据,即对源系统数据进行了清洗(去除了杂质)后的数据。
  • 数据应用层(DA或APP):前端应用直接读取的数据源;根据报表、专题分析需求而计算生成的数据。

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

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

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

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

1.5. 数仓的元数据管理

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

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

  • 构建数据仓库的主要步骤之一是ETL。这时元数据将发挥重要的作用,它定义了源数据系统到数据仓库的映射、数据转换的规则、数据仓库的逻辑结构、数据更新的规则、数据导入历史记录以及装载周期等相关内容。数据抽取和转换的专家以及数据仓库管理员正是通过元数据高效地构建数据仓库。
  • 用户在使用数据仓库时,通过元数据访问数据,明确数据项的含义以及定制报表。
  • 数据仓库的规模及其复杂性离不开正确的元数据管理,包括增加或移除外部数据源,改变数据清洗方法,控制出错的查询以及安排备份等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D12PIGvL-1647348827504)(http://ppw6n93dt.bkt.clouddn.com/5864e1b4d30797a11d68c8b8c745593f.png)]

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

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

2. Hive 的基本概念

Hive 简介

什么是 Hive

Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。

其本质是将SQL转换为MapReduce的任务进行运算,底层由HDFS来提供数据的存储,说白了hive可以理解为一个将SQL转换为MapReduce的任务的工具,甚至更进一步可以说hive就是一个MapReduce的客户端

为什么使用 Hive
  • 采用类SQL语法去操作数据,提供快速开发的能力。
  • 避免了去写MapReduce,减少开发人员的学习成本。
  • 功能扩展很方便。

2.2. Hive 架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jkQL8Lpw-1647348827504)(http://ppw6n93dt.bkt.clouddn.com/e2283a103fe1bfd137413d27e113e86b.png)]

  • 用户接口: 包括CLI、JDBC/ODBC、WebGUI。其中,CLI(command line interface)为shell命令行;JDBC/ODBC是Hive的JAVA实现,与传统数据库JDBC类似;WebGUI是通过浏览器访问Hive。
  • 元数据存储: 通常是存储在关系数据库如mysql/derby中。Hive 将元数据存储在数据库中。Hive 中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。
  • 解释器、编译器、优化器、执行器: 完成HQL 查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在HDFS 中,并在随后有MapReduce 调用执行。

Hive 与 Hadoop 的关系

Hive利用HDFS存储数据,利用MapReduce查询分析数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c2kWxMyy-1647348827505)(http://ppw6n93dt.bkt.clouddn.com/8fbf14cd38fa74bdcf5e76ae542d6350.png)]

Hive与传统数据库对比

hive用于海量数据的离线数据分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0oMpgpwH-1647348827505)(http://ppw6n93dt.bkt.clouddn.com/80c0b87d8202e0cdb5eaf7b8d44fd57a.png)]

总结:hive具有sql数据库的外表,但应用场景完全不同,hive只适合用来做批量数据统计分析

Hive 的安装

这里我们选用hive的版本是2.1.1
下载地址为:
http://archive.apache.org/dist/hive/hive-2.1.1/apache-hive-2.1.1-bin.tar.gz

下载之后,将我们的安装包上传到第三台机器的/export/softwares目录下面去

第一步:上传并解压安装包

将我们的hive的安装包上传到第三台服务器的/export/softwares路径下,然后进行解压

cd /export/softwares/
tar -zxvf apache-hive-2.1.1-bin.tar.gz -C ../servers/
第二步:安装mysql

第一步:在线安装mysql相关的软件包

yum install mysql mysql-server mysql-devel

第二步:启动mysql的服务

/etc/init.d/mysqld start

第三步:通过mysql安装自带脚本进行设置

/usr/bin/mysql_secure_installation

第四步:进入mysql的客户端然后进行授权

grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;

flush privileges;

第三步:修改hive的配置文件

修改hive-env.sh

cd /export/servers/apache-hive-2.1.1-bin/conf
cp hive-env.sh.template hive-env.sh
HADOOP_HOME=/export/servers/hadoop-2.7.5
export HIVE_CONF_DIR=/export/servers/apache-hive-2.1.1-bin/conf

修改hive-site.xml

cd /export/servers/apache-hive-2.1.1-bin/conf
vim hive-site.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
      <name>javax.jdo.option.ConnectionUserName</name>
      <value>root</value>
  </property>
  <property>
      <name>javax.jdo.option.ConnectionPassword</name>
      <value>123456</value>
  </property>
  <property>
      <name>javax.jdo.option.ConnectionURL</name>
      <value>jdbc:mysql://node03:3306/hive?createDatabaseIfNotExist=true&amp;useSSL=false</value>
  </property>
  <property>
      <name>javax.jdo.option.ConnectionDriverName</name>
      <value>com.mysql.jdbc.Driver</value>
  </property>
  <property>
      <name>hive.metastore.schema.verification</name>
      <value>false</value>
  </property>
  <property>
    <name>datanucleus.schema.autoCreateAll</name>
    <value>true</value>
 </property>
 <property>
		<name>hive.server2.thrift.bind.host</name>
		<value>node03</value>
   </property>
</configuration>
第四步:添加mysql的连接驱动包到hive的lib目录下

hive使用mysql作为元数据存储,必然需要连接mysql数据库,所以我们添加一个mysql的连接驱动包到hive的安装目录下,然后就可以准备启动hive了

将我们准备好的mysql-connector-java-5.1.38.jar 这个jar包直接上传到
/export/servers/apache-hive-2.1.1-bin/lib 这个目录下即可

至此,hive的安装部署已经完成,接下来我们来看下hive的三种交互方式

第五步:配置hive的环境变量

node03服务器执行以下命令配置hive的环境变量

sudo vim /etc/profile
export HIVE_HOME=/export/servers/apache-hive-2.1.1-bin
export PATH=:$HIVE_HOME/bin:$PATH

Hive 的交互方式

第一种交互方式 bin/hive
cd /export/servers/apache-hive-2.1.1-bin/
bin/hive

创建一个数据库

create database if not exists mytest;
第二种交互方式:使用sql语句或者sql脚本进行交互

不进入hive的客户端直接执行hive的hql语句

cd /export/servers/apache-hive-2.1.1-bin
bin/hive -e "create database if not exists mytest;"

或者我们可以将我们的hql语句写成一个sql脚本然后执行

cd /export/servers
vim  hive.sql
create database if not exists mytest;
use mytest;
create table stu(id int,name string);

通过hive -f 来执行我们的sql脚本

bin/hive -f /export/servers/hive.sql

Hive 的基本操作

###数据库操作

创建数据库

create database if not exists myhive;
use  myhive;

说明:hive的表存放位置模式是由hive-site.xml当中的一个属性指定的

<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>

创建数据库并指定位置

create database myhive2 location '/myhive2';

设置数据库键值对信息

数据库可以有一些描述性的键值对信息,在创建时添加:

create database foo with dbproperties ('owner'='itcast', 'date'='20190120');

查看数据库的键值对信息:

describe database extended foo;

修改数据库的键值对信息:

alter database foo set dbproperties ('owner'='itheima');

查看数据库更多详细信息

desc database extended  myhive2;

####删除数据库

删除一个空数据库,如果数据库下面有数据表,那么就会报错

drop  database  myhive2;

强制删除数据库,包含数据库下面的表一起删除

drop  database  myhive  cascade;   

数据库表操作

创建表的语法:

create [external] table [if not exists] table_name (
col_name data_type [comment '字段描述信息']
col_name data_type [comment '字段描述信息'])
[comment '表的描述信息']
[partitioned by (col_name data_type,...)]
[clustered by (col_name,col_name,...)]
[sorted by (col_name [asc|desc],...) into num_buckets buckets]
[row format row_format]
[storted as ....]
[location '指定表的路径']

说明:

  1. create table

创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常。

  1. external

可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。

  1. comment

表示注释,默认不能使用中文

  1. partitioned by

表示使用表分区,一个表可以拥有一个或者多个分区,每一个分区单独存在一个目录下 .

  1. clustered by
    对于每一个表分文件, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是 针对某一列进行桶的组织。

  2. sorted by

    指定排序字段和排序规则

  3. row format

​ 指定表文件字段分隔符

  1. storted as指定表文件的存储格式, 常用格式:SEQUENCEFILE, TEXTFILE, RCFILE,如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,使用 storted as SEQUENCEFILE。

  2. location

指定表文件的存储路径

内部表的操作

创建表时,如果没有使用external关键字,则该表是内部表(managed table)

Hive建表字段类型

分类类型描述字面量示例
原始类型BOOLEANtrue/falseTRUE
TINYINT1字节的有符号整数, -128~1271Y
SMALLINT2个字节的有符号整数,-32768~327671S
INT4个字节的带符号整数1
BIGINT8字节带符号整数1L
FLOAT4字节单精度浮点数1.0
DOUBLE8字节双精度浮点数1.0
DEICIMAL任意精度的带符号小数1.0
STRING字符串,变长“a”,’b’
VARCHAR变长字符串“a”,’b’
CHAR固定长度字符串“a”,’b’
BINARY字节数组无法表示
TIMESTAMP时间戳,毫秒值精度122327493795
DATE日期‘2016-03-29’
INTERVAL时间频率间隔
复杂类型ARRAY有序的的同类型的集合array(1,2)
MAPkey-value,key必须为原始类型,value可以任意类型map(‘a’,1,’b’,2)
STRUCT字段集合,类型可以不同struct(‘1’,1,1.0), named_stract(‘col1’,’1’,’col2’,1,’clo3’,1.0)
UNION在有限取值范围内的一个值create_union(1,’a’,63)

建表入门:

use myhive;
create table stu(id int,name string);
insert into stu values (1,"zhangsan");  #插入数据
select * from stu;

创建表并指定字段之间的分隔符

create  table if not exists stu2(id int ,name string) row format delimited fields terminated by '\t';

创建表并指定表文件的存放路径

create  table if not exists stu2(id int ,name string) row format delimited fields terminated by '\t' location '/user/stu2';

根据查询结果创建表

create table stu3 as select * from stu2; # 通过复制表结构和表内容创建新表

根据已经存在的表结构创建表

create table stu4 like stu;

查询表的详细信息

desc formatted  stu2;

. 删除表

drop table stu4;

外部表的操作

外部表说明

外部表因为是指定其他的hdfs路径的数据加载到表当中来,所以hive表会认为自己不完全独占这份数据,所以删除hive表的时候,数据仍然存放在hdfs当中,不会删掉.

内部表和外部表的使用场景

每天将收集到的网站日志定期流入HDFS文本文件。在外部表(原始日志表)的基础上做大量的统计分析,用到的中间表、结果表使用内部表存储,数据通过SELECT+INSERT进入内部表。

操作案例

分别创建老师与学生表外部表,并向表中加载数据

创建老师表

create external table teacher (t_id string,t_name string) row format delimited fields terminated by '\t';

创建学生表

create external table student (s_id string,s_name string,s_birth string , s_sex string ) row format delimited fields terminated by '\t';

加载数据

load data local inpath '/export/servers/hivedatas/student.csv' into table student;

加载数据并覆盖已有数据

load data local inpath '/export/servers/hivedatas/student.csv' overwrite  into table student;

从hdfs文件系统向表中加载数据(需要提前将数据上传到hdfs文件系统)

cd /export/servers/hivedatas
hdfs dfs -mkdir -p /hivedatas
hdfs dfs -put techer.csv /hivedatas/
load data inpath '/hivedatas/techer.csv' into table teacher;

分区表的操作

在大数据中,最常用的一种思想就是分治,我们可以把大的文件切割划分成一个个的小的文件,这样每次操作一个小的文件就会很容易了,同样的道理,在hive当中也是支持这种思想的,就是我们可以把大的数据,按照每月,或者天进行切分成一个个的小的文件,存放在不同的文件夹中.

创建分区表语法

create table score(s_id string,c_id string, s_score int) partitioned by (month string) row format delimited fields terminated by '\t';

创建一个表带多个分区

create table score2 (s_id string,c_id string, s_score int) partitioned by (year string,month string,day string) row format delimited fields terminated by '\t';

加载数据到分区表中

load data local inpath '/export/servers/hivedatas/score.csv' into table score partition (month='201806');

加载数据到多分区表中

load data local inpath '/export/servers/hivedatas/score.csv' into table score2 partition(year='2018',month='06',day='01');

多分区表联合查询(使用 union all)

select * from score where month = '201806' union all select * from score where month = '201806';

查看分区

show  partitions  score;

添加一个分区

alter table score add partition(month='201805');

删除分区

alter table score drop partition(month = '201806');

修改表结构

重命名:

alter  table  old_table_name  rename  to  new_table_name;

把表score4修改成score5

alter table score4 rename to score5;

增加/修改列信息:

  • 查询表结构
desc score5;
  • 添加列
alter table score5 add columns (mycol string, mysco int);
  • 更新列
alter table score5 change column mysco mysconew int; 
  • 删除表
drop table score5;

1.8. hive表中加载数据

直接向分区表中插入数据

create table score3 like score;

insert into table score3 partition(month ='201807') values ('001','002','100');

通过查询插入数据

通过load方式加载数据

load data local inpath '/export/servers/hivedatas/score.csv' overwrite into table score partition(month='201806');

通过查询方式加载数据

create table score4 like score;
insert overwrite table score4 partition(month = '201806') select s_id,c_id,s_score from score;

分区表综合练习

需求描述

现在有一个文件score.csv文件,存放在集群的这个目录下/scoredatas/month=201806,这个文件每天都会生成,存放到对应的日期文件夹下面去,文件别人也需要公用,不能移动。需求,创建hive对应的表,并将数据加载到表中,进行数据统计分析,且删除表之后,数据不能删除

数据准备

hdfs dfs -mkdir -p /scoredatas/month=201806
hdfs dfs -put score.csv /scoredatas/month=201806/

创建外部分区表,并指定文件数据存放目录

create external table score4(s_id string, c_id string,s_score int) partitioned by (month string) row format delimited fields terminated by '\t' location '/scoredatas';

进行表的修复(建立表与数据文件之间的一个关系映射)

msck  repair   table  score4;

分桶表操作

Hive的分区可以将整体数据划分成多个分区,从而优化查询,但是并非所有的数据都可以被合理的分区,会出现每个分区数据大小不一致的问题,有的分区数据量很大,有的分区数据量却很小,这就是常说的数据倾斜。为了解决分区可能带来的数据倾斜问题,Hive提供了分桶技术,就是将数据按照指定的字段进行划分到多个文件当中去,分桶就是MapReduce中的分区.

开启 Hive 的分桶功能

set hive.enforce.bucketing=true;

设置 Reduce 个数

set mapreduce.job.reduces=3;

创建分桶表

create table course_bucket(c_id string,c_name string,t_id string) clustered by(c_id) into 3 buckets row format delimited fields terminated by '\t';

注:根据c_id将数据划分到3个桶中,分桶的关键字是 clustered by()into ()buckets

将数据划分到几个桶中取决于设置的Reduce的个数

根据c_id实现分桶的原理:利用c_id的值获取一个哈希值,用哈希值对reduce的个数取模

desc formatted course_bucket;

桶表的数据加载,由于通标的数据加载通过hdfs dfs -put文件或者通过load data均不好使,只能通过insert overwrite

创建普通表,并通过insert overwriter的方式将普通表的数据通过查询的方式加载到桶表当中去

创建普通表

create table course_common (c_id string,c_name string,t_id string) row format delimited fields terminated by '\t';

普通表中加载数据

load data local inpath '/export/servers/hivedatas/course.csv' into table course_common;

通过insert overwrite给桶表中加载数据

insert overwrite table course_bucket select * from course_common cluster by(c_id);

查看分桶表信息

desc formatted course;

临时表操作

临时表是Hive数据表的一种特殊形式,临时表只对当前会话可见,数据被存储在用户的临时目录,并在会话结束时删除;

创建临时表的命令:

create temporary table hive_temporary(name string,age int,gender string) row format delimited fields terminated by ‘\t’;

当退出hive以后再启动hive时会发现此时hive_temporary表已经不存在了。

视图操作

视图是从数据库中选取出来的数据组成的逻辑窗口,它是一个虚拟机表。引入试图后,用户可以将注意力集中在关心的数据上,如果数据来源于多个基本表结构,并且搜索条件比较复杂时,需要编写的查询语句就会比较繁琐,此时可以通过视图将数据查询语句变得简单可行。

创建视图

创建视图命令:

create view hive_view comment “This is a view table” as select c_id from course_common;

查询视图信息

desc formatted hive_view; 查看hive_view的详细结构信息

desc hive_view; 查看hive_view的基本结构信息

Hive数据类型

基本数据类型

表6-1

Hive数据类型Java数据类型长度例子
TINYINTbyte1byte有符号整数20
SMALINTshort2byte有符号整数20
INTint4byte有符号整数20
BIGINTlong8byte有符号整数20
BOOLEANboolean布尔类型,true或者falseTRUE FALSE
FLOATfloat单精度浮点数3.14159
DOUBLEdouble双精度浮点数3.14159
STRINGstring字符系列。可以指定字符集。可以使用单引号或者双引号。‘now is the time’ “for all good men”
TIMESTAMP时间类型
BINARY字节数组

对于Hive的String类型相当于数据库的varchar类型,该类型是一个可变的字符串,不过它不能声明其中最多能存储多少个字符,理论上它可以存储2GB的字符数。

集合数据类型

表6-2

数据类型描述语法示例
STRUCT和c语言中的struct类似,都可以通过“点”符号访问元素内容。例如,如果某个列的数据类型是STRUCT{first STRING, last STRING},那么第1个元素可以通过字段.first来引用。struct()
MAPMAP是一组键-值对元组集合,使用数组表示法可以访问数据。例如,如果某个列的数据类型是MAP,其中键->值对是’first’->’John’和’last’->’Doe’,那么可以通过字段名[‘last’]获取最后一个元素map()
ARRAY数组是一组具有相同类型和名称的变量的集合。这些变量称为数组的元素,每个数组元素都有一个编号,编号从零开始。例如,数组值为[‘John’, ‘Doe’],那么第2个元素可以通过数组名[1]进行引用。Array()

Hive有三种复杂数据类型ARRAY、MAP 和 STRUCT。ARRAY和MAP与Java中的Array和Map类似,而STRUCT与C语言中的Struct类似,它封装了一个命名字段集合,复杂数据类型允许任意层次的嵌套。

案例实操

1) 假设某表有如下一行,我们用JSON格式来表示其数据结构。在Hive下访问的格式为

{

​ “name”: “mengmeng”,

​ “friends”: [“bingbing”, “lili”] , //列表Array,

​ “children”: { //键值Map,

​ “xiao meng”: 18 ,

​ “xiaoxiao meng”: 19

​ }

​ “address”: { //结构Struct,

​ “street”: “hui longguan” ,

​ “city”: “beijing”

​ }

}

2)基于上述数据结构,我们在Hive里创建对应的表,并导入数据。

创建本地测试文件test.txt

mengmeng,bingbing_lili,xiaomeng:18_xiaoxiao meng:19,hui long guan_beijing

yangyang,caicai_susu,xiaoyang:18_xiaoxiao yang:19,chao yang_beijing

注意:MAP,STRUCT和ARRAY里的元素间关系都可以用同一个字符表示,这里用“_”。

3)Hive上创建测试表test

create table test(name string,friends array,children map<string,int>,address structstreet:string,city:string) row format delimited fields terminated by’,’ collection items terminated by ‘_’ map keys terminated by’:’ lines terminated by ‘\n’;

字段解释:

row format delimited fields terminated by ‘,’ – 列分隔符

collection items terminated by ‘_’ --MAP STRUCT 和 ARRAY 的分隔符(数据分割符号)

map keys terminated by ‘:’ --MAP中的key与value的分隔符

lines terminated by ‘\n’; --行分隔符

4)导入文本数据到测试表 或者直接put到这个目录也可以

hive (default)> load data local inpath ‘/home/hadoop/test.txt’ into table test

5)访问三种集合列里的数据,以下分别是ARRAY,MAP,STRUCT的访问方式

hive (default)>select friends[1],children[‘xiao meng’],address.city from test where name=“mengmeng”;

OK

_c0 _c1 city

lili 18 beijing

Timetaken: 0.076 seconds, Fetched: 1 row(s)

4. Hive 查询语法

SELECT

SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list [HAVING condition]]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list]
]
[LIMIT number]
  1. order by 会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。
  2. sort by不是全局排序,其在数据进入reducer前完成排序。因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只保证每个reducer的输出有序,不保证全局有序,可以设置reduces的个数:set mapreduce.job.reduces=XX。
  3. distribute by(字段)根据指定的字段将数据分到不同的reducer,且分发算法是hash散列。
  4. cluster by(字段) 除了具有distribute by的功能外,还会对该字段进行排序.

因此,如果distribute 和sort字段是同一个时,此时,cluster by = distribute by + sort by

查询语法

全表查询

select * from score;

选择特定列

select s_id ,c_id from score;

列别名

1)重命名一个列。
2)便于计算。
3)紧跟列名,也可以在列名和别名之间加入关键字‘AS’

select s_id as myid ,c_id from score;

LIMIT语句

典型的查询会返回多行数据。LIMIT子句用于限制返回的行数。

select * from score limit 3;

排序

全局排序

Order By:全局排序,一个reduce

  1. 使用 ORDER BY 子句排序
    ASC(ascend): 升序(默认)
    DESC(descend): 降序

  2. ORDER BY 子句在SELECT语句的结尾。

  3. 案例实操

    1. 查询学生的成绩,并按照分数降序排列
    SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score DESC;
    
    1. 查询学生的成绩,并按照分数升序排列
    SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score asc;
    

按照别名排序

按照分数的平均值排序

select s_id ,avg(s_score) avg from score group by s_id order by avg;

多个列排序

按照学生id和平均成绩进行排序

select s_id ,avg(s_score) avg from score group by s_id order by s_id,avg;

每个MapReduce内部排序(Sort By)局部排序

Sort By:每个MapReduce内部进行排序,对全局结果集来说不是排序。

  1. 设置reduce个数
set mapreduce.job.reduces=3;
  1. 查看设置reduce个数
set mapreduce.job.reduces;
  1. 查询成绩按照成绩降序排列
select * from score sort by s_score desc;
  1. 将查询结果导入到文件中(按照成绩降序排列)
insert overwrite local directory '/export/servers/hivedatas/sort' select * from score sort by s_score desc;

常用函数

  • 求总行数(count)
select count(1) from score;
  • 求分数的最大值(max)
select max(s_score) from score;
  • 求分数的最小值(min)
select min(s_score) from score;
  • 求分数的总和(sum)
select sum(s_score) from score;
  • 求分数的平均值(avg)
select avg(s_score) from score;

WHERE语句

  1. 使用WHERE 子句,将不满足条件的行过滤掉。
  2. WHERE 子句紧随 FROM 子句。
  3. 案例实操

查询出分数大于60的数据

select * from score where s_score > 60;

比较运算符

操作符支持的数据类型描述
A=B基本数据类型如果A等于B则返回TRUE,反之返回FALSE
A<=>B基本数据类型如果A和B都为NULL,则返回TRUE,其他的和等号(=)操作符的结果一致,如果任一为NULL则结果为NULL
A<>B, A!=B基本数据类型A或者B为NULL则返回NULL;如果A不等于B,则返回TRUE,反之返回FALSE
A<B基本数据类型A或者B为NULL,则返回NULL;如果A小于B,则返回TRUE,反之返回FALSE
A<=B基本数据类型A或者B为NULL,则返回NULL;如果A小于等于B,则返回TRUE,反之返回FALSE
A>B基本数据类型A或者B为NULL,则返回NULL;如果A大于B,则返回TRUE,反之返回FALSE
A>=B基本数据类型A或者B为NULL,则返回NULL;如果A大于等于B,则返回TRUE,反之返回FALSE
A [NOT] BETWEEN B AND C基本数据类型如果A,B或者C任一为NULL,则结果为NULL。如果A的值大于等于B而且小于或等于C,则结果为TRUE,反之为FALSE。如果使用NOT关键字则可达到相反的效果。
A IS NULL所有数据类型如果A等于NULL,则返回TRUE,反之返回FALSE
A IS NOT NULL所有数据类型如果A不等于NULL,则返回TRUE,反之返回FALSE
IN(数值1, 数值2)所有数据类型使用 IN运算显示列表中的值
A [NOT] LIKE BSTRING 类型B是一个SQL下的简单正则表达式,如果A与其匹配的话,则返回TRUE;反之返回FALSE。B的表达式说明如下:‘x%’表示A必须以字母‘x’开头,‘%x’表示A必须以字母’x’结尾,而‘%x%’表示A包含有字母’x’,可以位于开头,结尾或者字符串中间。如果使用NOT关键字则可达到相反的效果。
A RLIKE B, A REGEXP BSTRING类型 B是一个正则表达式,如果A与其匹配,则返回TRUE;反之返回FALSE。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。例如,正则表达式必须和整个字符串A相匹配,而不是只需与其字符串匹配。
  • 查询分数等于80的所有的数据
select * from score where s_score = 80;
  • 查询分数在80到100的所有数据
select * from score where s_score between 80 and 100;
  • 查询成绩为空的所有数据
select * from score where s_score is null;
  • 查询成绩是80和90的数据
select * from score where s_score in(80,90);

LIKE 和 RLIKE

  1. 使用LIKE运算选择类似的值
  2. 选择条件可以包含字符或数字:
% 代表零个或多个字符(任意个字符)。
_ 代表一个字符。
  1. RLIKE子句是Hive中这个功能的一个扩展,其可以通过Java的正则表达式这个更强大的语言来指定匹配条件。

  2. 案例实操

    1. 查找以8开头的所有成绩
    	select * from score where s_score like '8%';
    
    1. 查找第二个数值为9的所有成绩数据
    select * from score where s_score like '_9%';
    
    1. 查找s_id中含1的数据
    select * from score where s_id rlike '[1]';  #  like '%1%'
    

逻辑运算符

操作符含义
AND逻辑并
OR逻辑或
NOT逻辑否
  • 查询成绩大于80,并且s_id是01的数据
select * from score where s_score >80 and s_id = '01';
  • 查询成绩大于80,或者s_id 是01的数
select * from score where s_score > 80 or s_id = '01';
  • 查询s_id 不是 01和02的学生
select * from score where s_id not in ('01','02');

分组

GROUP BY 语句

GROUP BY语句通常会和聚合函数一起使用,按照一个或者多个列队结果进行分组,然后对每个组执行聚合操作。
案例实操:

  • 计算每个学生的平均分数
select s_id ,avg(s_score) from score group by s_id;
  • 计算每个学生最高成绩
select s_id ,max(s_score) from score group by s_id;

HAVING 语句

  1. having与where不同点

    1. where针对表中的列发挥作用,查询数据;having针对查询结果中的列发挥作用,筛选数据。
    2. where后面不能写分组函数,而having后面可以使用分组函数。
    3. having只用于group by分组统计语句。
  2. 案例实操:

    • 求每个学生的平均分数
    select s_id ,avg(s_score) from score group by s_id;
    
    • 求每个学生平均分数大于85的人
    select s_id ,avg(s_score) avgscore from score group by s_id having avgscore > 85;
    

JOIN 语句

等值 JOIN

Hive支持通常的SQL JOIN语句,但是只支持等值连接,不支持非等值连接。

案例操作: 查询分数对应的姓名

select s.s_id,s.s_score,stu.s_name,stu.s_birth  from score s  join student stu on s.s_id = stu.s_id;

表的别名

  • 好处

    • 使用别名可以简化查询。
    • 使用表名前缀可以提高执行效率。
  • 案例实操

    • 合并老师与课程表
    select * from techer t join course c on t.t_id = c.t_id;
    

内连接

内连接:只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来。

select * from techer t inner join course c on t.t_id = c.t_id;

左外连接

左外连接:JOIN操作符左边表中符合WHERE子句的所有记录将会被返回。
查询老师对应的课程

select * from techer t left join course c on t.t_id = c.t_id;

右外连接

右外连接:JOIN操作符右边表中符合WHERE子句的所有记录将会被返回。

select * from teacher t right join course c on t.t_id = c.t_id;

多表连接

注意:连接 n个表,至少需要n-1个连接条件。例如:连接三个表,至少需要两个连接条件。

多表连接查询,查询老师对应的课程,以及对应的分数,对应的学生

select * from teacher t
left join course c
on t.t_id = c.t_id
left join score s
on s.c_id = c.c_id
left join student stu
on s.s_id = stu.s_id;

大多数情况下,Hive会对每对JOIN连接对象启动一个MapReduce任务。本例中会首先启动一个MapReduce job对表techer和表course进行连接操作,然后会再启动一个MapReduce job将第一个MapReduce job的输出和表score;进行连接操作。

问题:如何将表合并以后的数据保存到本地?

课堂作业:
新建一个dept和emp表,并将department.txt和employee.txt数据导入相应的表中,进行如下操作:
1.内连接
查询部门代码,部门名称,员工姓名,员工薪水
select dept.deptno,dept.dname,emp.ename,emp.sal from
dept join emp on dept.deptno=emp.deptno;
------------

查询部门代码为30的部门代码,部门名称,员工姓名,员工薪水
select dept.deptno,dept.dname,emp.ename,emp.sal from
dept join emp on dept.deptno=emp.deptno
where dept.deptno='30';
-------------

查询每个部门的人数,结果字段包含部门名称、人数
select dept.dname,count(dept.deptno)
from emp join dept on dept.deptno=emp.deptno
group by dept.dname;
--------------


2.自然联结
使用自然联结查询部门代码,部门名称,员工姓名,员工薪水
select dname,ename,sal from dept natural join emp;
----------------




3.左外联结
使用左外联结查询部门代码,部门名称,员工姓名,员工薪水
(员工表作为左表,部门表作为右表)
select dept.deptno,dept.dname,emp.ename,emp.sal
from emp
left outer join dept
on dept.deptno=emp.deptno;
-----------------


4.右外联结
使用右外联结查询部门代码,部门名称,员工姓名,员工薪水
(员工表作为左表,部门表作为右表)
select dept.deptno,dept.dname,emp.ename,emp.sal
from emp
right outer join dept
on dept.deptno=emp.deptno;
-----------------


师对应的课程,以及对应的分数,对应的学生

select * from teacher t
left join course c
on t.t_id = c.t_id
left join score s
on s.c_id = c.c_id
left join student stu
on s.s_id = stu.s_id;

大多数情况下,Hive会对每对JOIN连接对象启动一个MapReduce任务。本例中会首先启动一个MapReduce job对表techer和表course进行连接操作,然后会再启动一个MapReduce job将第一个MapReduce job的输出和表score;进行连接操作。

问题:如何将表合并以后的数据保存到本地?

课堂作业:
新建一个dept和emp表,并将department.txt和employee.txt数据导入相应的表中,进行如下操作:
1.内连接
查询部门代码,部门名称,员工姓名,员工薪水
select dept.deptno,dept.dname,emp.ename,emp.sal from
dept join emp on dept.deptno=emp.deptno;
------------

查询部门代码为30的部门代码,部门名称,员工姓名,员工薪水
select dept.deptno,dept.dname,emp.ename,emp.sal from
dept join emp on dept.deptno=emp.deptno
where dept.deptno='30';
-------------

查询每个部门的人数,结果字段包含部门名称、人数
select dept.dname,count(dept.deptno)
from emp join dept on dept.deptno=emp.deptno
group by dept.dname;
--------------


2.自然联结
使用自然联结查询部门代码,部门名称,员工姓名,员工薪水
select dname,ename,sal from dept natural join emp;
----------------




3.左外联结
使用左外联结查询部门代码,部门名称,员工姓名,员工薪水
(员工表作为左表,部门表作为右表)
select dept.deptno,dept.dname,emp.ename,emp.sal
from emp
left outer join dept
on dept.deptno=emp.deptno;
-----------------


4.右外联结
使用右外联结查询部门代码,部门名称,员工姓名,员工薪水
(员工表作为左表,部门表作为右表)
select dept.deptno,dept.dname,emp.ename,emp.sal
from emp
right outer join dept
on dept.deptno=emp.deptno;
-----------------


  • 0
    点赞
  • 14
    收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

✎重逢之时

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值