英文名称为Data Warehouse,可简写为DW或DWH。数据仓库的目的是构建面向分析的集成化数据环境,为企业提供决策支持(Decision Support)。
数据仓库是存数据的,企业的各种数据往里面存,主要目的是为了分析有效数据,后续会基于它产出供分析挖掘的数据,或者数据应用需要的数据,如企业的分析性报告和各类报表等。
可以理解为:面向分析的存储系统
。
数据仓库是面向主题的(Subject-Oriented )、集成的(Integrated)、非易失的(Non-Volatile)和时变的(Time-Variant )数据集合,用以支持管理决策。
数据仓库是面向主题的,数据仓库通过一个个主题域将多个业务系统的数据加载到一起,为了各个主题(如:用户、订单、商品等)进行分析而建,操作型数据库是为了支撑各种业务而建立。
数据仓库会将不同源数据库中的数据汇总到一起,数据仓库中的综合数据不能从原有的数据库系统直接得到。因此在数据进入数据仓库之前,必然要经过统一与整合,这一步是数据仓库建设中最关键、最复杂的一步(ETL),要统一源数据中所有矛盾之处,如字段的同名异义、异名同义、单位不统一、字长不一致,等等。
操作型数据库主要服务于日常的业务操作,使得数据库需要不断地对数据实时更新,以便迅速获得当前最新数据,不至于影响正常的业务运作。
在数据仓库中只要保存过去的业务数据,不需要每一笔业务都实时更新数据仓库,而是根据商业需要每隔一段时间把一批较新的数据导入数据仓库。
数据仓库的数据反映的是一段相当长的时间内历史数据的内容,是不同时点的数据库的集合,以及基于这些快照进行统计、综合和重组的导出数据。数据仓库中的数据一般仅执行查询操作,很少会有删除和更新。但是需定期加载和刷新数据。
数据仓库包含各种粒度的历史数据。数据仓库中的数据可能与某个特定日期、星期、月份、季度或者年份有关。数据仓库的目的是通过分析企业过去一段时间业务的经营状况,挖掘其中隐藏的模式。虽然数据仓库的用户不能修改数据,但并不是说数据仓库的数据是永远不变的。分析的结果只能反映过去的情况,当业务变化后,挖掘出的模式会失去时效性。因此数据仓库的数据需要定时更新,以适应决策的需要。
数据库与数据仓库的区别实际讲的是 OLTP
与 OLAP
的区别。
操作型处理,叫联机事务处理 OLTP(On-Line Transaction Processing,),也可以称面向交易的处理系统,它是针对具体业务在数据库联机的日常操作,通常对少数记录进行查询、修改。用户较为关心操作的响应时间、数据的安全性、完整性和并发支持的用户数等问题。传统的数据库系统作为数据管理的主要手段,主要用于操作型处理。
分析型处理,叫联机分析处理 OLAP(On-Line Analytical Processing)一般针对某些主题的历史数据进行分析,支持 管理决策。
首先要明白,数据仓库的出现,并不是要取代数据库。
数据仓库,是在数据库已经大量存在的情况下,为了进一步挖掘数据资源、为了决策需要而产生的,它决不是所谓的“大型数据库”。
按照数据流入流出的过程,数据仓库架构可分为三层——源数据、数据仓库、数据应用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XPs5FFUf-1647348827503)(http://ppw6n93dt.bkt.clouddn.com/d312300d6dcbf0a66412ad4ec422236d.png)]
数据仓库的数据来源于不同的源数据,并提供多样的数据应用,数据自下而上流入数据仓库后向上层开放应用,而数据仓库只是中间集成化数据管理的一个平台。
源数据层(ODS)
:此层数据无任何更改,直接沿用外围系统数据结构和数据,不对外开放;为临时存储层,是接口数据的临时存储区域,为后一步的数据处理做准备。数据仓库层(DW)
:也称为细节层,DW层的数据应该是一致的、准确的、干净的数据,即对源系统数据进行了清洗(去除了杂质)后的数据。数据应用层(DA或APP)
:前端应用直接读取的数据源;根据报表、专题分析需求而计算生成的数据。数据仓库从各数据源获取数据及在数据仓库内的数据转换和流动都可以认为是ETL(抽取Extra, 转化Transfer, 装载Load)的过程,ETL是数据仓库的流水线,也可以认为是数据仓库的血液,它维系着数据仓库中数据的新陈代谢,而数据仓库日常的管理和维护工作的大部分精力就是保持ETL的正常和稳定。
用空间换时间,通过大量的预处理来提升应用系统的用户体验(效率),因此数据仓库会存在大量冗余的数据;不分层的话,如果源业务系统的业务规则发生变化将会影响整个数据清洗过程,工作量巨大。
通过数据分层管理可以简化数据清洗的过程,因为把原来一步的工作分到了多个步骤去完成,相当于把一个复杂的工作拆成了多个简单的工作,把一个大的黑盒变成了一个白盒,每一层的处理逻辑都相对简单和容易理解,这样我们比较容易保证每一个步骤的正确性,当数据发生错误的时候,往往我们只需要局部调整某个步骤即可。
元数据(Meta Date),主要记录数据仓库中模型的定义、各层级间的映射关系、监控数据仓库的数据状态及ETL的任务运行状态。一般会通过元数据资料库(Metadata Repository)来统一地存储和管理元数据,其主要目的是使数据仓库的设计、部署、操作和管理能达成协同和一致。
元数据是数据仓库管理系统的重要组成部分,元数据管理是企业级数据仓库中的关键组件,贯穿数据仓库构建的整个过程,直接影响着数据仓库的构建、使用和维护。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D12PIGvL-1647348827504)(http://ppw6n93dt.bkt.clouddn.com/5864e1b4d30797a11d68c8b8c745593f.png)]
元数据可分为技术元数据和业务元数据。技术元数据为开发和管理数据仓库的IT 人员使用,它描述了与数据仓库开发、管理和维护相关的数据,包括数据源信息、数据转换描述、数据仓库模型、数据清洗与更新规则、数据映射和访问权限等。而业务元数据为管理层和业务分析人员服务,从业务角度描述数据,包括商务术语、数据仓库中有什么数据、数据的位置和数据的可用性等,帮助业务人员更好地理解数据仓库中哪些数据是可用的以及如何使用。
由上可见,元数据不仅定义了数据仓库中数据的模式、来源、抽取和转换规则等,而且是整个数据仓库系统运行的基础,元数据把数据仓库系统中各个松散的组件联系起来,组成了一个有机的整体。
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。
其本质是将SQL转换为MapReduce的任务进行运算,底层由HDFS来提供数据的存储,说白了hive可以理解为一个将SQL转换为MapReduce的任务的工具,甚至更进一步可以说hive就是一个MapReduce的客户端
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jkQL8Lpw-1647348827504)(http://ppw6n93dt.bkt.clouddn.com/e2283a103fe1bfd137413d27e113e86b.png)]
Hive利用HDFS存储数据,利用MapReduce查询分析数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c2kWxMyy-1647348827505)(http://ppw6n93dt.bkt.clouddn.com/8fbf14cd38fa74bdcf5e76ae542d6350.png)]
hive用于海量数据的离线数据分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0oMpgpwH-1647348827505)(http://ppw6n93dt.bkt.clouddn.com/80c0b87d8202e0cdb5eaf7b8d44fd57a.png)]
总结:hive具有sql数据库的外表,但应用场景完全不同,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相关的软件包
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-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
<configuration>
<property>
<name>javax.jdo.option.ConnectionUserNamename>
<value>rootvalue>
property>
<property>
<name>javax.jdo.option.ConnectionPasswordname>
<value>123456value>
property>
<property>
<name>javax.jdo.option.ConnectionURLname>
<value>jdbc:mysql://node03:3306/hive?createDatabaseIfNotExist=true&useSSL=falsevalue>
property>
<property>
<name>javax.jdo.option.ConnectionDriverNamename>
<value>com.mysql.jdbc.Drivervalue>
property>
<property>
<name>hive.metastore.schema.verificationname>
<value>falsevalue>
property>
<property>
<name>datanucleus.schema.autoCreateAllname>
<value>truevalue>
property>
<property>
<name>hive.server2.thrift.bind.hostname>
<value>node03value>
property>
configuration>
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的三种交互方式
node03服务器执行以下命令配置hive的环境变量
sudo vim /etc/profile
export HIVE_HOME=/export/servers/apache-hive-2.1.1-bin
export PATH=:$HIVE_HOME/bin:$PATH
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
###数据库操作
create database if not exists myhive;
use myhive;
说明:hive的表存放位置模式是由hive-site.xml当中的一个属性指定的
<name>hive.metastore.warehouse.dirname>
<value>/user/hive/warehousevalue>
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 '指定表的路径']
说明:
创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常。
可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
表示注释,默认不能使用中文
表示使用表分区,一个表可以拥有一个或者多个分区,每一个分区单独存在一个目录下 .
clustered by
对于每一个表分文件, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是 针对某一列进行桶的组织。
sorted by
指定排序字段和排序规则
row format
指定表文件字段分隔符
storted as指定表文件的存储格式, 常用格式:SEQUENCEFILE, TEXTFILE, RCFILE,如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,使用 storted as SEQUENCEFILE。
location
指定表文件的存储路径
创建表时,如果没有使用external关键字,则该表是内部表(managed table)
Hive建表字段类型
分类 | 类型 | 描述 | 字面量示例 |
---|---|---|---|
原始类型 | BOOLEAN | true/false | TRUE |
TINYINT | 1字节的有符号整数, -128~127 | 1Y | |
SMALLINT | 2个字节的有符号整数,-32768~32767 | 1S | |
INT | 4个字节的带符号整数 | 1 | |
BIGINT | 8字节带符号整数 | 1L | |
FLOAT | 4字节单精度浮点数 | 1.0 | |
DOUBLE | 8字节双精度浮点数 | 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) |
MAP | key-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的基本结构信息
表6-1
Hive数据类型 | Java数据类型 | 长度 | 例子 |
---|---|---|---|
TINYINT | byte | 1byte有符号整数 | 20 |
SMALINT | short | 2byte有符号整数 | 20 |
INT | int | 4byte有符号整数 | 20 |
BIGINT | long | 8byte有符号整数 | 20 |
BOOLEAN | boolean | 布尔类型,true或者false | TRUE FALSE |
FLOAT | float | 单精度浮点数 | 3.14159 |
DOUBLE | double | 双精度浮点数 | 3.14159 |
STRING | string | 字符系列。可以指定字符集。可以使用单引号或者双引号。 | ‘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() |
MAP | MAP是一组键-值对元组集合,使用数组表示法可以访问数据。例如,如果某个列的数据类型是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
字段解释:
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)
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]
因此,如果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子句用于限制返回的行数。
select * from score limit 3;
Order By:全局排序,一个reduce
使用 ORDER BY 子句排序
ASC(ascend): 升序(默认)
DESC(descend): 降序
ORDER BY 子句在SELECT语句的结尾。
案例实操
SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score DESC;
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;
Sort By:每个MapReduce内部进行排序,对全局结果集来说不是排序。
set mapreduce.job.reduces=3;
set mapreduce.job.reduces;
select * from score sort by s_score desc;
insert overwrite local directory '/export/servers/hivedatas/sort' select * from score sort by s_score desc;
select count(1) from score;
select max(s_score) from score;
select min(s_score) from score;
select sum(s_score) from score;
select avg(s_score) from score;
查询出分数大于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 | 基本数据类型 | 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 B | STRING 类型 | B是一个SQL下的简单正则表达式,如果A与其匹配的话,则返回TRUE;反之返回FALSE。B的表达式说明如下:‘x%’表示A必须以字母‘x’开头,‘%x’表示A必须以字母’x’结尾,而‘%x%’表示A包含有字母’x’,可以位于开头,结尾或者字符串中间。如果使用NOT关键字则可达到相反的效果。 |
A RLIKE B, A REGEXP B | STRING | 类型 B是一个正则表达式,如果A与其匹配,则返回TRUE;反之返回FALSE。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。例如,正则表达式必须和整个字符串A相匹配,而不是只需与其字符串匹配。 |
select * from score where s_score = 80;
select * from score where s_score between 80 and 100;
select * from score where s_score is null;
select * from score where s_score in(80,90);
% 代表零个或多个字符(任意个字符)。
_ 代表一个字符。
RLIKE子句是Hive中这个功能的一个扩展,其可以通过Java的正则表达式这个更强大的语言来指定匹配条件。
案例实操
select * from score where s_score like '8%';
select * from score where s_score like '_9%';
select * from score where s_id rlike '[1]'; # like '%1%'
操作符 | 含义 |
---|---|
AND | 逻辑并 |
OR | 逻辑或 |
NOT | 逻辑否 |
select * from score where s_score >80 and s_id = '01';
select * from score where s_score > 80 or s_id = '01';
select * from score where s_id not in ('01','02');
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与where不同点
案例实操:
select s_id ,avg(s_score) from score group by s_id;
select s_id ,avg(s_score) avgscore from score group by s_id having avgscore > 85;
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;
-----------------