hive
一、HIVE是什么
开发调试麻烦
只能用java开发
需要对hadoop的底层及api比较了解才能开发复杂代码
HQL
Hive是基于Hadoop的一个数据仓库工具。可以将结构化的数据文件映射为一张数据库表,并提供完整的sql查询功能,可以将sql语句转换为MapReduce任务进行运行。其优点是学习成本低,可以通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库的统计分析。
Hive是建立在 Hadoop 上的数据仓库基础构架。它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储、查询和分析存储在 Hadoop 中的大规模数据的机制。Hive 定义了简单的类 SQL 查询语言,称为 HiveQL,它允许熟悉 SQL 的用户查询数据。同时,这个语言也允许熟悉 MapReduce 开发者的开发自定义的 mapper 和 reducer 来处理内建的 mapper 和 reducer 无法完成的复杂的分析工作。
Hive不支持在线事务处理,也不支持行级的插入和更新和删除。
----
数据仓库简介
数据仓库,是为企业所有级别的决策制定过程,提供所有类型数据支持的战略集合。它是单个数据存储,出于分析性报告和决策支持目的而创建。 为需要业务智能的企业,提供指导业务流程改进、监视时间、成本、质量以及控制。
----
ETL:Extract-Transform-Load(抽取、转换、登录)
二、HIVE的安装配置
首先需要hadoop的支持,启动好hadoop
下载:从apache官网下载新版本hive,要注意和hadoop版本的匹配。
支持:
需要对应版本jdk的支持
需要安装并运行hadoop
安装:
将下载好的hive安装包上传到linux中。
解压:tar -zxvf apache-hive-1.2.0-bin.tar.gz
启动:
进入hive/bin目录,直接运行hive命令,即可进入hive提示符。
hive不需要任何配置就可以运行,因为它可以通过HADOOP_HOME环境变量获知hadoop的配置信息。
------------
可能的安装冲突解决:
问题描述:
在使用hadoop2.5.x环境下,启动hive发现报错:
java.lang.IncompatibleClassChangeError: Found class jline.Terminal, but interface was expected
问题分析:
造成这个错误的原因是因为 jline.Terminal这个类有错误。
经过检查发现,在hadoop/share/hadoop/yarn/lib目录下存在jline-0.9.x.jar
而在hive/lib/目录下存在jline-2.12.jar
重复的包不兼容造成了此问题。
解决方法:
复制hive/lib/jline-2.12.jar替换hadoop/share/hadoop/yarn/lib中的jline-0.9.x.jar,重启hadoop和hive即可。
或
直接将hadoop升级到更高版本,如2.7.x中已经解决此问题。
------------
三、HIVE入门
$show databases;
执行后发现默认有一个库default
$show tables;
发现没有任何表,证明不use其他库时,默认就是default库。
$create database tedu;
发现在hdfs中多出了/user/hive/warehouse/tedu.db目录
结论1:hive中的数据库对应hdfs中/user/hive/warehouse目录下以.db结尾的目录。
$use tedu;
$create table student (id int,name string);
$show tables;
$desc student;
$show create table student;
发现正确创建出来了表。
发现在hdfs中多出了/user/hive/warehouse/tedu.db/sutdent目录
结论2:hive中的表对应hdfs/user/hive/warehouse/[db目录]中的一个目录
$load data local inpath '../mydata/student.txt' into table student;
发现/user/hive/warehouse/tedu.db/sutdent下多出了文件
$select * from student;
发现查出的数据不正确,原因是建表时没有指定分隔符。默认的分隔符是空格。
$create table student2 (id int,name string) row format delimited fields terminated by '\t';
$load data local inpath '../mydata/student.txt' into table student2;
$select * from student2;
发现正确查询出了数据。
结论3:hive中的数据对应当前hive表对应的hdfs目录中的文件。
$select count(*) from student;
发现执行了mapreduce作业,最终现实了结果
结论4:hive会将命令转换为mapreduce执行。
$use default;
$create table teacher(id int,name string);
发现在hive对应的目录下多出了 tedu.db 文件夹,其中包含user文件夹。
结论5:hive默认的default数据库直接对应/user/hive/warehouse目录,在default库中创建的表直接会在该目录下创建对应目录。
##hive安装详解+替换元数据储存的数据库
mysql资源下载,密码:alrj
0.安装Jdk、hadoop、hive
Hadoop必须启动才能启动hive,登录到hadoop01下才能在hive下执行语句
1.hive数据仓库特点
(1)数据库是文件夹、表是文件夹、数据是文件
(2)insert into tabxvalues(1,"aaaa");
(3)本地上传文件
(4)selectcount(*) from tabx;
(5)default数据库下建表存放位置在/user/hive/warehouse
create table tabx2(id int,name string) rowformat delimited fields terminated by '\t';
2.不在原先目录(例如bin)存储元数据的数据库找不到了只剩下一个默认的库default
因为默认存储元数据的数据库是derby数据库,该数据库只能存储固定目录下的元数据
元数据只能存储在mysql或derby数据库中,所以得更换元数据存储的数据库
(1)安装mysql
[1]rpm -qa|grep -i mysql 查看是否装有mysql(rpm -qa查看linux装有什么软件)
[2]rpm -ev --nodeps 名字 卸载原先的mysql软件(--nodeps不考虑依赖强制卸载)
[3]groupadd mysql 增加用户组,要用到
[4]useradd -r -g mysql mysql 往用户组中添加用户
[5]rpm –ivh 名字 安装rpm包,客户端、服务端的mysql两个
rpm -ivhMySQL-server-5.6.29-1.linux_glibc2.5.x86_64.rpm
rpm -ivhMySQL-client-5.6.29-1.linux_glibc2.5.x86_64.rpm
[6]my.cnf linux下的mysql核心配置文件改字符集(my.ini mysql核心配置文件 端口、字符集)
vim /usr/my.cnf
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
character_set_server=utf8
# basedir = .....
# datadir = .....
# port = .....
# server_id = .....
# socket = .....
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
[7]cp /usr/share/mysql//mysql.server /etc/init.d/mysqld 将mysqld加入系统服务
[8]service mysqld start开启
[9]mysql –u root –p 输入密码root后发现登录不进去,是因为他自己生成密码
[10]vim /root/.mysql_secret 找随机密码,登录mysql成功
[11]mysqladmin –u root –p password root(新密码) 修改新密码
方法一:
在mysql系统外,使用mysqladmin
# mysqladmin -u root -p password root
Enter password: 【输入原来的密码】
[12]\s 可看系统信息
2)修改hive元数据库
[1]删除原先数据,存在derby数据库中的元数据
[2]cp hive-default.xml.templatehive-site.xml
在<configuration>中进行配置
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://hadoop01:3306/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>root</value>
<description>password to use against metastore database</description>
</property>
[3]./hive 报错 可知缺少驱动包,上传mysql驱动包 mysql-commad。。。。
[4]./hive
提示连接被拒绝,给权限,让权限生效
登录进入mysql:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;
如果还报错再给赋予一次权限::
登录进入mysql将百分号(通配符)改为你自己的机器:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'hadoop01' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;
[5]还是不能进入hive
因为我的mysql配置了主从复制
从错误看到貌似是statement模式不足以应付应用,换成mixed试试看吧:
mysql> STOP SLAVE;
Query OK, 0 rows affected (0.02 sec)
mysql> SET GLOBAL binlog_format=MIXED;
Query OK, 0 rows affected (0.00 sec)
mysql> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
但是这样只会一次性
为了永久生效,需要修改my.ini
# Remove leading
# to turn on a very important data integrity option: logging
# changes to the binary log between backups.
log_bin = E:/mysql56/log_bin/log_bin.log
#relay_log = E:/mysql56/log_bin/relay_log.log
#read_only = 1
# binary logging format - mixed recommended
binlog_format=mixed
[5]进入hive(所创建的库)后,创建库ok;创建表时发现卡了;
进mysql看hive(创建的库)的字符集,是utf8,但是hive只支持iso8859-1(latin1)
Show create database hive;看字符集
Drop database hive;删
create database hive charset latin1;重建存放元数据的库指定字符集为latin1
问题全部解决。
通过数据库第三方软件查看mysql中存储元数据的库hive(元数据库)
DBS:数据库
TBLS:managerd table内部表
COLLMNS_V2:列的信息
SDS:表对应的存储位置
四、外部表、内部表、分区表、分桶表
1、外部表
外部表
创建hive表,经过检查发现TBLS表中,hive表的类型为MANAGED_TABLE.
在真实开发中,很可能在hdfs中已经有了数据,希望通过hive直接使用这些数据作为表内容。
此时可以直接创建出hdfs文件夹,其中放置数据,再在hive中创建表管来管理,这种方式创建出来的表叫做外部表。
#创建目录,上传已有文件
hadoop fs -mkdir /data
hadoop fs -put student.txt /datax
hadoop fs -put student.txt /datax
#在hive中创建外部表管理已有数据
create external table ext_student(id int ,name string) row format delimited fields terminated by '\t' location '/datax';
经过检查发现可以使用其中的数据。成功的建立了一张外部表。
#vim ppp.txt
1 x
2 y
3 z
#hadoop fs - put ppp.txt /datax/
再在该目录下手动创建文件,能不能查询出来呢?
发现是可以的。
不管是内部表还是外部表,新增的文件都可以自动被应用。
在删除表时,内部表一旦删除对应元数据和hdfs中的文件夹和文件都会被删除。外部表只删除元数据,对应的hdfs中的文件夹和文件不会被删除。
2、内部表
先有表后有数据
$create table student2 (id int,name string) row format delimited fields terminated by '\t';
$load data local inpath '../mydata/student.txt' into table student2;
$select * from student2;
发现正确查询出了数据。
3、分区表
六、分区表
hive也支持分区表
对数据进行分区可以提高查询时的效率
普通表和分区表区别:有大量数据增加的需要建分区表
create table book (id bigint, name string) partitioned by (category string) row format delimited fields terminated by '\t';
create table book (id bigint, name string) partitioned by (category string,gender string) row format delimited fields terminated by '\t';
所谓的分区表是又在表文件夹下创建了子文件夹([分区的名]=分区名字的值 )分别存放同一张表中不同分区的数据。
从而将数据分区存放,提高按照分区查询数据时的效率。
所以当数据量比较大,而且数据经常要按照某个字段作为条件进行查询时,最好按照该条件进行分区存放。
通过观察元数据库,发现,分区表也会当作元数据存放在SDS表中。
**如果手动的创建分区目录,是无法被表识别到的,因为在元数据库中并没有该分区的信息,如果想让手动创建的分区能够被表识别需要在元数据库SDS表中增加分区的元数据信息。
ALTER TABLE book add PARTITION (category = 'jp',gender='male') location '/user/hive/warehouse/testx.db/book/category=jp/gender=male';
4、分桶表
hive也支持分桶表
分桶操作是更细粒度的分配方式
一张表可以同时分区和分桶
分桶的原理是根据指定的列的计算hash值模余分桶数量后将数据分开存放
分桶的主要作用是:对于一个庞大的数据集我们经常需要拿出来一小部分作为样例,然后在样例上验证我们的查询,优化我们的程序
创建带桶的 table :
create table teacher(id int,name string) clustered by (id) into 4 buckets row format delimited fields terminated by '\t';
强制多个 reduce 进行输出:
set hive.enforce.bucketing=true;
往表中插入数据:
insert overwrite table teacher select * from temp;//需要提前准备好temp,从temp查询数据写入到teacher
查看表的结构,会发现当前表下有四个文件:
dfs -ls /user/hive/warehouse/teacher;
读取数据,看一个文件的数据:
dfs -cat /user/hive/warehouse/teacher/000000_0;
//桶使用 hash 来实现,所以每个文件拥有的数据的个数都有可能不相等。
对桶中的数据进行采样:
select * from teacher tablesample(bucket 1 out of 4 on id);
//桶的个数从1开始计数,前面的查询从4个桶中的第一个桶获取数据。其实就是四分之一。
查询一半返回的桶数:
select * from bucketed_user tablesample(bucket 1 out of 2 on id);
//桶的个数从1开始计数,前2个桶中的第一个桶获取数据。其实就是二分之一。
五、hive语法
0.数据类型
TINYINT - byte
SMALLINT - short
INT - int
BIGINT - long
BOOLEAN - boolean
FLOAT - float
DOUBLE - double
STRING - String
TIMESTAMP - TimeStamp
BINARY - byte[]
1.create table
CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXIST 选项来忽略这个异常。
EXTERNAL 关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
LIKE 允许用户复制现有的表结构,但是不复制数据。
有分区的表可以在创建的时候使用 PARTITIONED BY 语句。一个表可以拥有一个或者多个分区,每一个分区单独存在一个目录下。
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], ...)]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
[CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
[
[ROW FORMAT row_format] [STORED AS file_format]
| STORED BY 'storage.handler.class.name' [ WITH SERDEPROPERTIES (...) ] (Note: only available starting with 0.6.0)
]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)] (Note: only available starting with 0.6.0)
[AS select_statement] (Note: this feature is only available starting with 0.5.0.)
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
LIKE existing_table_name
[LOCATION hdfs_path]
data_type
: primitive_type
| array_type
| map_type
| struct_type
primitive_type
: TINYINT
| SMALLINT
| INT
| BIGINT
| BOOLEAN
| FLOAT
| DOUBLE
| STRING
array_type
: ARRAY < data_type >
map_type
: MAP < primitive_type, data_type >
struct_type
: STRUCT < col_name : data_type [COMMENT col_comment], ...>
row_format
: DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
| SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
file_format:
: SEQUENCEFILE
| TEXTFILE
| RCFILE (Note: only available starting with 0.6.0)
| INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
练习:
创建一张内部表
create table xx (id int,name string) row format DELIMITED FIELDS TERMINATED BY '\t';
创建一张外部表
create external table xx (id int,name string) row format DELIMITED FIELDS TERMINATED BY '\t';
创建一张带有分区的外部表
create external table xx (id int,name string) row format DELIMITED FIELDS TERMINATED BY '\t' partitioned by 'ccc';
2.Alter Table
(1)Add Partitions
ALTER TABLE table_name ADD [IF NOT EXISTS] partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ...
partition_spec:
: PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...)
练习:修改表增加分区
(2)Drop Partitions
ALTER TABLE table_name DROP partition_spec, partition_spec,...
(3)Rename Table
ALTER TABLE table_name RENAME TO new_table_name
(4)Change Column
ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]
这个命令可以允许改变列名、数据类型、注释、列位置或者它们的任意组合
(5)Add/Replace Columns
ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)
ADD是代表新增一字段,字段位置在所有列后面(partition列前);REPLACE则是表示替换表中所有字段。
3.Show
查看表名
SHOW DATABASES;
SHOW TABLES;
查看表名,部分匹配
SHOW TABLES 'page.*';
SHOW TABLES '.*view';
查看某表的所有Partition,如果没有就报错:
SHOW PARTITIONS page_view;
查看某表结构:
DESCRIBE invites;
DESC invites;
查看分区内容
SELECT a.foo FROM invites a WHERE a.ds='2008-08-15';
查看有限行内容,同Greenplum,用limit关键词
SELECT a.foo FROM invites a limit 3;
查看表分区定义
DESCRIBE EXTENDED page_view PARTITION (ds='2008-08-08');
4.Load
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
Load 操作只是单纯的复制/移动操作,将数据文件移动到 Hive 表对应的位置。
5.Insert
(1)Inserting data into Hive Tables from queries
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement
(2)Writing data into filesystem from queries
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 SELECT ... FROM ...
6.Drop
删除一个内部表的同时会同时删除表的元数据和数据。删除一个外部表,只删除元数据而保留数据。
7.Limit
Limit 可以限制查询的记录数。查询的结果是随机选择的
8.Select
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[ CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT number]
9.JOIN
join_table:
table_reference JOIN table_factor [join_condition]
| table_reference {LEFT|RIGHT|FULL} [OUTER] JOIN table_reference join_condition
| table_reference LEFT SEMI JOIN table_reference join_condition
table_reference:
table_factor
| join_table
table_factor:
tbl_name [alias]
| table_subquery alias
| ( table_references )
join_condition:
ON equality_expression ( AND equality_expression )*
equality_expression:
expression = expression
Hive文件格式(创建表时STORE AS 的四种类型)
六、hive内置函数
七、hive的UDF
把字母全变大写
Java工程,导包,将linux下安装的hive包解压后将lib中的所有jar包都导入工程即可编写自己的UDF
写文件
打jar包,放到lib下
Create temporary function myUpper as‘cn.tedu.udf.ToUpperUdf’;将jar包和一个名字对应
Select myUpper(‘adfdsfDD’);自定义UDF完成了。
八、HIVE的java API操作
hive实现了jdbc接口,所以可以非常方便用jdbc技术通过java代码操作。
1.在服务器端开启HiveServer服务
./hive--service hiveserver2
2.创建本地工程,导入jar包
导入hive\lib目录下的hive-jdbc-1.2.0-standalone.jar
导入hadoop-2.7.1\share\hadoop\common下的hadoop-common-2.7.1.jar
3.编写jdbc代码执行
九、案例
flume(扇入,拦截器,hdfs sink转义字符,)、hive(外部表)、sqoop实操案例、echarts展示
(1)flume收集数据到hdfs中
#example.conf:单节点Flume配置
#命名Agent a1的组件
a1.sources = r1
a1.sinks = k1
a1.channels = c1
#描述/配置Source
a1.sources.r1.type = spooldir
a1.sources.r1.spoolDir=/home/software/apache-flume-1.6.0-bin/zebardata
a1.sources.r1.interceptors=i1
a1.sources.r1.interceptors.i1.type=timestamp
#描述Sink
a1.sinks.k1.type=avro
a1.sinks.k1.hostname=192.168.239.129
a1.sinks.k1.port=41414
#描述内存Channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
#为Channle绑定Source和Sink
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
#example.conf£ºµ¥½ÚµãFlumeÅäÖÃ
#ÃüÃûAgent a1µÄ×é¼þ
a1.sources = r1
a1.sinks = k1
a1.channels = c1
#ÃèÊö/ÅäÖÃSource
a1.sources.r1.type = spooldir
a1.sources.r1.spoolDir=/home/software/apache-flume-1.6.0-bin/zebardata
a1.sources.r1.interceptors=i1
a1.sources.r1.interceptors.i1.type=timestamp
#ÃèÊöSink
a1.sinks.k1.type=avro
a1.sinks.k1.hostname=192.168.239.129
a1.sinks.k1.port=41414
#ÃèÊöÄÚ´æChannel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
#ΪChannle°ó¶¨SourceºÍSink
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
#example.conf:单节点Flume配置
#命名Agent a1的组件
a1.sources = r1
a1.sinks = k1
a1.channels = c1
#描述/配置Source
a1.sources.r1.type = avro
a1.sources.r1.bind = 0.0.0.0
a1.sources.r1.port = 41414
#描述Sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = hdfs://hadoop01:9000/zebra/reportTime=%Y-%m-%d-%H-00-00 #以每个小时作为一个文件夹
#--文件格式:默认SequenceFile,可选 DataStream \ CompressedStream
a1.sinks.k1.hdfs.fileType = DataStream #DataStream可以直接读出来
a1.sinks.k1.hdfs.filePrefix = %Y-%m-%d-%H-%M-%S
a1.sinks.k1.hdfs.fileSuffix = .data
#这里配置的是60秒,文件滚动一次,也就每隔60秒,会新产生一个文件
a1.sinks.k1.hdfs.rollInterval=10
#--触发roll操作的文件大小in bytes (0: never roll based on file size)
a1.sinks.k1.hdfs.rollSize=0
#--在roll操作之前写入文件的事件数量(0 = never roll based on number of events)
a1.sinks.k1.hdfs.rollCount=0
#描述内存Channel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
#为Channle绑定Source和Sink
a1.sources.r1.channels = c1
(2)hive(外部表)处理
(3)sqoop
(4)echarts展示
上一篇: hive