Hive 的产生
Hive 产生的原因:方便非java 编程者(熟悉 SQL 语言)对 hdfs 的数据做 mapreduce操作。
Hive 是数据仓库
数据库:用户与数据库交互,提交 SQL 语句后,马上见到执行结果;存放业务数据;数据库提出范式的概念是为了解决数据冗余和耦合的问题;数据库给业务数据提供存储支撑。
数据仓库:不与用户交互;存放历史数据;反范式设计,专门引入冗余数据,保证数据完整。数据仓库面向分析,里面存放的数据用来做分析和挖掘。
Hive 将 SQL 转化为 MapReduce 可以识别的操作,承担解释器、编译器、优化器等角色
Hive 运行时,元数据(表的结构、属性)存储在关系型数据库里面。因为元数据信息需要高效的读取。
用户接口主要有三个:Client(命令行),JDBC/ODBC 和 WEBGUI。其中最常用的是 Client,Client 启动的时候,会同时启动一个Hive 副本。Client 是 Hive 的客户端,用户连接至 Hive Server。在启动 Client 模式的时候,需要指出 Hive Server 所在节点,并且在该节点启动 Hive Server。 WEB GUI 是通过浏览器访问 Hive。
Hive将元数据存储在数据库中,如 mysql、derby。Hive 中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。
解释器、编译器、优化器完成 HQL 查询语句从词法分析、语法分析、编译、优化以及
查询计划的生成。生成的查询计划存储在 HDFS 中,并在随后有 MapReduce调用执行。编译器将一个 Hive QL 转换操作符,操作符是 Hive 的最小的处理单元每个操作符代表 HDFS 的一个操作或者一道 MapReduce 作业。
Operator 是 hive 定义的一个处理过程,是一个树形结构:
protected List<Operator<? extends Serializable>> childOperators; protected List<Operator<? extends Serializable>> parentOperators; protectedboolean done; // 初始化值为false
Hive 的数据存储在 HDFS中,大部分的查询、计算由 MapReduce 完成(包含*的查询,比如 select * from tbl 不会生成 MapRedcue任务)。
Hive 语法解析
ANTLR词法语法分析工具解析 HQL
Hive 的三种模式
Local 模式
此模式连接到一个In-memory 的数据库 Derby,一般用于 UnitTest
单用户模式通过网络连接到一个数据库中,是最经常使用到的模式。
多用户模式
远程服务器模式。用于非 Java 客户端访问元数据库,在服务器端启动
MetaStoreServer,客户端利用 Thrift协议通过 MetaStoreServer 访问元数据库。
Linux 下安装 MySQL
1. yum 安装mysql
[root@node01 ~]# yum install mysql-server
2. 启动 mysqld服务
[root@node01 ~]# service mysqld start
3. 修改 mysql修改权限
[root@node01 ~]# mysql mysql> show databases; mysql> use mysql; mysql> show tables; mysql> select host,user from user; +------------------+------+ | host | user | +------------------+------+ | 127.0.0.1 | root | | localhost | | | localhost | root | | node01 | | | node01 | root | +-----------------+-------+ mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION; mysql> select host,user from user; +--------------+------+ | host | user | +--------------+------+ | % | root | | 127.0.0.1 | root | | localhost | | | localhost | root | | node01 | | | node01 | root | +---------------+------+ mysql> delete from mysql.user where host != '%'; mysql> flush privileges; |
4.重新登录 mysql
[root@node01 ~]# mysql -u root -p
Hive 安装
本地模式(derby)
这种方式是最简单的存储方式,只需要在 hive-site.xml 做如下配置便可
<?xml version="1.0"?>
<?xml-stylesheettype="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:derby:;databaseName=metastore_db;create=true</value> </property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>org.apache.derby.jdbc.EmbeddedDriver</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>true</value>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
</configuration>
注:使用 derby 存储方式时,运行hive 会在当前目录生成一个 derby 文件和一个 metastore_db 目录。这种存储方式的弊端是在同一个目录下同时只能有一个 hive 客户端能使用数据库,否则会提示如下错误
hive> show tables;
FAILED: Error in metadata:javax.jdo.JDOFatalDataStoreException: Failed to start database 'metast ore_db',see the next exception for details.
NestedThrowables:
java.sql.SQLException: Failed to startdatabase 'metastore_db', see the next exception for details.
FAILED: Execution Error, return code 1from org.apache.hadoop.hive.ql.exec.DDLTask
单用户模式(mysql)
这种存储方式需要在本地运行一个 mysql 服务器,并作如下配置(下面两种使用 mysql 的方式,需要将 mysql 的 jar 包拷贝到$HIVE_HOME/lib 目录下)。
<?xml version="1.0"?>
<?xml-stylesheettype="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- hive_remote 是数据库名称,同时安装不同的模式,连接的数据库要不同-->
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive_remote/warehouse</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost/hive_remote?createDatabaseIfNotExist=true</value> </property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>password</value>
</property>
</configuration>
多用户模式
Remot 一体
这种存储方式需要在远端服务器运行一个 mysql 服务器,并且需要在 Hive 服务器启动meta 服务。
这里用 mysql 的测试服务器,ip 位 192.168.1.214,新建 hive_remote 数据库,字符集 latine1
<?xml version="1.0"?>
<?xml-stylesheettype="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://192.168.57.6:3306/hive?createDatabaseIfNotExist=true</value> </property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>password</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>false</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://192.168.1.188:9083</value>
</property>
</configuration> 注:这里把 hive 的服务端和客户端都放在同一台服务器上了。服务端和客户端可以拆开。
Remot 分开
将 hive-site.xml 配置文件拆为如下两部分
服务端配置文件
<?xml version="1.0"?>
<?xml-stylesheettype="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://192.168.57.6:3306/hive?createDatabaseIfNotExist=true</value> </property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
</configuration>
客户端配置文件
<?xml version="1.0"?>
<?xml-stylesheettype="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>false</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://192.168.57.5:9083</value>
</property>
</configuration>
安装单用户模式具体步骤
1. 解压 hive 包
[root@node02 sxt]# tar xf apache-hive-1.2.1-bin.tar.gz
2. 配置环境变量
[root@node02 sxt]# vi + /etc/profile export HIVE_PREFIX=/opt/sxt/apache-hive-1.2.1-bin export PATH=$JAVA_HOME/bin:$PATH:$HADOOP_PREFIX/bin:$HADOOP_PREFIX/sbin:$ZOOKEEPER_ PREFIX/bin:$HIVE_PREFIX/bin [root@node02 apache-hive-1.2.1-bin]# . /etc/profile |
3. 修改配置文件
[root@node02 sxt]# cd apache-hive-1.2.1-bin/conf
[root@node02 conf]# cp hive-default.xml.templatehive-site.xml
[root@node02 conf]# vi hive-site.xml
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name> <value>/user/hive_remote/warehouse</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://node01/hive_remote?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
</configuration>
4.把 JDBC驱动包放到 Hive lib 目录下
5. 让 hadoop 的 jline 包和 hive 的 jline 包版本保持一致(高版本替换低版本)
[root@node02 conf]# cd /opt/sxt/apache-hive-1.2.1-bin/lib
[root@node02 conf]# cp jline-2.12.jar/opt/sxt/hadoop-2.6.5/share/hadoop/yarn/lib/
[root@node02 conf]# cd/opt/sxt/hadoop-2.6.5/share/hadoop/yarn/lib/
[root@node02 lib]# rm -f jline-0.9.94.jar
6. 启动 Hive
[root@node02 lib]# hive hive> 客户端启动的时候要注意:
[ERROR] Terminal initialization failed;falling back to unsupported java.lang.IncompatibleClassChangeError: Found classjline.Terminal, but interface was expected atjline.TerminalFactory.create(TerminalFactory.java:101)
错误的原因: Hadoop jline 版本和 hive 的 jline 不一致
一些简单的操作
hive> create table table01 (id int, name string);hive> show tables; hive> desc table01; hive> insert into table01values(1,'Jed');
安装多用户模式具体步骤
角色划分
mysql |
MetaStoreServer |
Hive 客户端 |
|
node01 |
√ |
|
|
node03 |
|
|
√ |
node04 |
|
√ |
|
1. 将 hive 文件夹 copy到 node03、node04
[root@node02 sxt]# scp -r apache-hive-1.2.1-binnode03:`pwd`
[root@node02 sxt]# scp -r apache-hive-1.2.1-binnode04:`pwd`
2. 把 node02的环境变量配置文件 copy 到 node03、node04
[root@node02 sxt]# scp /etc/profile node03:/etc/
[root@node02 sxt]# scp /etc/profile node03:/etc/
[root@node03 ~]# . /etc/profile
[root@node04 ~]# . /etc/profile
3.修改 node03(客户端)的hive 的配置文件
[root@node03 conf]# vi hive-site.xml
<configuration>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<property>
<name>hive.metastore.local</name>
<value>false</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://node04:9083</value>
</property>
</configuration>
4. 修改node04(服务端)的配置文件
[root@node04 conf]# vi hive-site.xml <configuration>
<property> <name>hive.metastore.warehouse.dir</name> <value>/user/hive/warehouse</value> </property>
<property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://node01:3306/hive?createDatabaseIfNotExist=true</value> </property>
<property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.jdbc.Driver</value> </property>
<property> <name>javax.jdo.option.ConnectionUserName</name> |
<value>root</value> </property>
<property> <name>javax.jdo.option.ConnectionPassword</name> <value>123456</value> </property>
</configuration> |
5. 使node03 和 node04 的 jline 包和 hadoop 包保持版本一致
6. 启动 hive 服务端
[root@node04 lib]# hive --service metastore
7.启动客户端
[root@node03 lib]# hive
注意:mysql 驱动包放置在服务器端,jline 放置在客户端
Hive 的数据类型
primitive_type:
array_type、 map_type、struct_type
TINYINT、SMALLINT、INT、BIGINT、BOOLEAN、FLOAT、DOUBLE、STRING
DDL(DataDefinition Language)
Create Database
CREATE (DATABASE|SCHEMA) [IF NOT EXISTS]database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, ...)];
DropDatabase
DROP (DATABASE|SCHEMA) [IF EXISTS]database_name [RESTRICT|CASCADE];
Alter Database
ALTER (DATABASE|SCHEMA) database_name SETDBPROPERTIES
(property_name=property_value,...); -- (Note: SCHEMA added in Hive0.14.0)
ALTER (DATABASE|SCHEMA) database_name SETOWNER [USER|ROLE] user_or_role; --(Note: Hive 0.13.0 and later; SCHEMA added in Hive 0.14.0)
Use Database
USE database_name;
USE DEFAULT;
CreateTable
CREATE [TEMPORARY] [EXTERNAL] TABLE [IFNOT EXISTS] [db_name.]table_name --(Note:
TEMPORARY available in Hive 0.14.0 andlater)
[(col_name data_type [COMMENT col_comment], ...[constraint_specification])]
[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]
[SKEWED BY (col_name, col_name, ...) -- (Note: Available in Hive0.10.0 and later)]
ON ((col_value, col_value, ...), (col_value, col_value, ...), ...)
[STORED AS DIRECTORIES]
[
[ROW FORMAT row_format]
[STOREDAS file_format]
| STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES(...)] -- (Note:
Available in Hive 0.6.0 and later)
]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)] -- (Note: Available in Hive 0.6.0 and later)
[AS select_statement]; -- (Note:Available in Hive 0.5.0 and later; not supported for external tables)
CREATE [TEMPORARY] [EXTERNAL] TABLE [IFNOT EXISTS] [db_name.]table_name
LIKE existing_table_or_view_name
[LOCATION hdfs_path];
data_type : primitive_type
|array_type
|map_type
|struct_type
|union_type -- (Note: Available in Hive0.7.0 and later)
primitive_type : TINYINT
|SMALLINT
|INT
|BIGINT
|BOOLEAN
|FLOAT
|DOUBLE
|DOUBLE PRECISION -- (Note: Available in Hive 2.2.0 and later)
|STRING
|BINARY -- (Note: Available in Hive0.8.0 and later)
|TIMESTAMP -- (Note: Available in Hive0.8.0 and later)
|DECIMAL -- (Note: Available in Hive0.11.0 and later)
|DECIMAL(precision, scale) -- (Note:Available in Hive 0.13.0 and later)
|DATE -- (Note: Available in Hive0.12.0 and later)
|VARCHAR -- (Note: Available in Hive0.12.0 and later)
|CHAR -- (Note: Available in Hive0.13.0 and later)
array_type
:ARRAY < data_type >
map_type
:MAP < primitive_type, data_type >
struct_type
:STRUCT < col_name : data_type [COMMENT col_comment], ...>
union_type
:UNIONTYPE < data_type, data_type, ... > -- (Note: Available in Hive 0.7.0 and later)
row_format
:DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS
TERMINATED BY char]
[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char(换行符,默认'\n')]
[NULL DEFINED AS char] -- (Note: Available in Hive 0.13 andlater) | SERDE serde_name [WITHSERDEPROPERTIES (property_name=property_value, property_name=property_value,...)]
file_format:
:SEQUENCEFILE
|TEXTFILE -- (Default, depending on hive.default.fileformatconfiguration)
|RCFILE -- (Note: Available in Hive0.6.0 and later)
|ORC -- (Note: Available in Hive0.11.0 and later)
|PARQUET -- (Note: Available in Hive0.13.0 and later)
|AVRO -- (Note: Available in Hive0.14.0 and later)
|INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
constraint_specification:
:[, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE ]
[, CONSTRAINTconstraint_name FOREIGN KEY (col_name, ...) REFERENCES table_name(col_name,...) DISABLE NOVALIDATE
例子
人员表 id、name、hobbyies、address 1,Jed,book-lol-game,beijing:haidian-shanghai:pudong 2,Tom,book-lol-lanqiu,beijing:xisanqi-shanghai:lujiazui 内部表:数据存放在配置文件指定的目录下,删除内部表后,其中的数据也会删除 <property> <name>hive.metastore.warehouse.dir</name> <value>/user/hive/warehouse</value> </property> create table person0 ( id int, name string, hobbies ARRAY<string>, address MAP<string,string> ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' #字段之间用','分隔 COLLECTION ITEMS TERMINATED BY '-' #数组元素之间用'-'分隔 MAP KEYS TERMINATED BY ':'; #Map 元素之间用':'分隔 外部表:数据存放在建表时自定义的路径下,删除外部表后,其中的数据没有被删除,只是删除了元数据 create EXTERNAL table person1 ( id int, name string, likes ARRAY<string>, address MAP<string,string> ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' |
COLLECTION ITEMSTERMINATED BY '-'
MAP KEYSTERMINATED BY ':'
LOCATION'/user/root/person1';
create tableperson2 as select id, hobbies from person0; #MapReduce
create tableperson3 like person0; #不是 MapReduce任务
Loading files into tables
LOAD DATA [LOCAL] INPATH 'filepath'[OVERWRITE] INTO TABLE tablename [PARTITION
(partcol1=val1, partcol2=val2 ...)]
load data localinpath '/tmp/data/person0_data' into table person0;
分区
分区:分区的字段不能是表中已有的字段 create table person4 ( id int, name string, likes ARRAY<string>, address MAP<string,string> ) PARTITIONED BY (sex string) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' COLLECTION ITEMS TERMINATED BY '-' MAP KEYS TERMINATED BY ':'; load data local inpath '/tmp/data/person0_data' into table person4 PARTITION (sex='1'); load data local inpath '/tmp/data/person0_data' into table person4 PARTITION (sex='2'); |
hive> select *from person4;
1 Jed ["book","lol"]{"beijing":"chaoyang"} 1
2 Tom["book","lol","sports"] {"beijing":"chaoyang","shanghai":"pudong"}1
3 Cat["book","lol","sports","music"]
{"beijing":"chaoyang","shanghai":"pudong","shanxi":"taiyuan"}1
1 Jed["book","lol"] {"beijing":"chaoyang"} 2
2 Tom["book","lol","sports"] {"beijing":"chaoyang","shanghai":"pudong"}2
3 Cat ["book","lol","sports","music"] {"beijing":"chaoyang","shanghai":"pudong","shanxi":"taiyuan"} 2 hive> select * from person4 where sex="1"; 1 Jed ["book","lol"] {"beijing":"chaoyang"} 1 2 Tom ["book","lol","sports"] {"beijing":"chaoyang","shanghai":"pudong"} 1 3 Cat ["book","lol","sports","music"] {"beijing":"chaoyang","shanghai":"pudong","shanxi":"taiyuan"} 1 create table person6 ( id int, name string, likes ARRAY<string>, address MAP<string,string> ) PARTITIONED BY (sex string, age int) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' COLLECTION ITEMS TERMINATED BY '-' MAP KEYS TERMINATED BY ':'; hive> load data local inpath '/tmp/data/person6_data' into table person6 PARTITION (sex='1',age=18); hive> load data local inpath '/tmp/data/person6_data' into table person6 PARTITION (sex='2',age=18); hive> load data local inpath '/tmp/data/person6_data' into table person6 PARTITION (sex='3',age=20); 添加/删除分区,内部表删除分区后该分区下的数据也会被删除,外部表删除分区后该分区下的数据不会被删除 ALTER TABLE person4 add PARTITION (sex='3'); ALTER TABLE person6 drop PARTITION (sex='1',age=18); ALTER TABLE person6 drop PARTITION (sex='2');#会删除 sex='2'和 age=18 ALTER TABLE person4 drop PARTITION (age=20); #会删除 sex='3'和 age=20 |
DML(DataManipulation Language)
load data inpath 'hdfs path' into tabletable_name
这个操作实际是把 hdfs path 下的文件移动到了 hive 配置的存放的数据的目录下
load data local inpath 'hdfs path' intotable table_name
这个操作实际是把本地的文件上传到 hdfs 的临时目录下,然后把该文件移动到了 hive 配置的存放的数据的目录下多次load 相同的文件,数据会追加,而不是覆盖
hive> create table person7 like person0; 常用于分析某张表,把结果放入另一张表 from log insert into table result select …… hive> from person0 > insert into table person7 > select id,name,hobbies,address; |
使用 Beeline 连接 Hive
服务端启动 hiveserver2
[root@node04 ~]# hiveserver2
|
客户端进入 beeline 并连接
[root@node03 ~]# beeline Beeline version 1.2.1 by Apache Hive beeline> !connect jdbc:hive2://node04:10000 Connecting to jdbc:hive2://node04:10000 Enter username for jdbc:hive2://node04:10000: root Enter password for jdbc:hive2://node04:10000: ****** Connected to: Apache Hive (version 1.2.1) Driver: Hive JDBC (version 1.2.1) Transaction isolation: TRANSACTION_REPEATABLE_READ 0: jdbc:hive2://node04:10000> |
退出连接
0: jdbc:hive2://node04:10000> !quit
另一种连接方法
[root@node03 ~]# beeline -u jdbc:hive2//node04:10000 -nroot
Hive JDBC
项目依赖包:hive 安装包 lib 根目录下所有包,hadoop项目依赖的包
package com.sxt.hive.jdbc;
import java.sql.SQLException;
import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.sql.DriverManager; public class HiveJDBC { private static String driverName = "org.apache.hive.jdbc.HiveDriver"; public static void main(String[] args) throws SQLException { try { Class.forName(driverName); } catch (ClassNotFoundException e) { e.printStackTrace(); System.exit(1); }
Connection conn = DriverManager.getConnection( "jdbc:hive2://node04:10000/default", "root", "");
Statement stmt = conn.createStatement();
String sql = "select * from person7 limit 5"; ResultSet res = stmt.executeQuery(sql); while (res.next()) { //输出第1列和name那一列 System.out.println(res.getString(1) + "-" + res.getString("name")); } } } |
Regex
数据: 192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] "GET /bg-upper.png HTTP/1.1" 304 - 192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] "GET /bg-button.png HTTP/1.1" 304 - 192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] "GET / HTTP/1.1" 200 11217 SQL: CREATE TABLE log ( host STRING, identity STRING, |
t_user STRING, time STRING, request STRING, referer STRING, agent STRING ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' WITH SERDEPROPERTIES ( "input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) \\[(.*)\\] \"(.*)\" (-|[0-9]*) (-|[0-9]*)" ) STORED AS TEXTFILE; load data local inpath "/tmp/data/log.txt" into table log; hive> select * from log; 192.168.57.4 - - 29/Feb/2016:18:14:35 +0800 GET /bg-upper.png HTTP/1.1 304 - 192.168.57.4 - - 29/Feb/2016:18:14:35 +0800 GET /bg-button.png HTTP/1.1 304 - 192.168.57.4 - - 29/Feb/2016:18:14:36 +0800 GET / HTTP/1.1 200 11217 ROW FORMAT 不会破坏原数据的结构 |
函数
内置运算符关系运算符
运算符 |
类型 |
说明 |
A = B |
所有原始类型 |
如果 A 与 B 相等,返回 TRUE,否则返回 FALSE |
A == B |
无 |
失败,因为无效的语法。 SQL 使用“=”,不使用 “==”。 |
A <> B |
所有原始类型 |
如果 A 不等于 B 返回 TRUE,否则返回 FALSE。如果 A 或 B 值为“NULL”,结果返回“NULL”。 |
A < B |
所有原始类型 |
如果 A 小于 B 返回 TRUE,否则返回 FALSE。如果 A 或 B 值为“NULL”,结果返回“NULL”。 |
A <= B |
所有原始类型 |
如果 A 小于等于 B 返回 TRUE,否则返回 FALSE。如果 A 或 B 值为“NULL”,结果返回“NULL”。 |
A > B |
所有原始类型 |
如果 A 大于 B 返回 TRUE,否则返回 FALSE。如果 A 或 B 值为“NULL”,结果返回“NULL”。 |
A >= B |
所有原始类型 |
如果 A 大于等于 B 返回 TRUE,否则返回 FALSE。如果 A 或 B 值为“NULL”,结果返回“NULL”。 |
A IS NULL |
所有类型 |
如果 A 值为“NULL”,返回 TRUE,否则返回 FALSE |
A IS NOT NULL |
所有类型 |
如果 A 值不为“NULL”,返回 TRUE,否则返回 FALSE |
A LIKE B |
字符串 |
如果 A 或 B 值为“NULL”,结果返回”NULL”。 字符串 A 与 B 通过 sql 进行匹配,如果相符返回 TRUE,不符返回 FALSE。 B 字符串中 的“_”代表任一字符,“%”则代表多个任意 字符。例如: ("foobar " like "foo ")返回 FALSE,("foobar " like "foo_ _ _ "或者"foobar " like "foo% ")则返回 TURE |
A RLIKE B |
字符串 |
如果 A 或 B 值为“NULL”,结果返回”NULL”。 字符串 A 与 B 通过 java 进行匹配,如果相符返回 TRUE, 不符返回 FALSE。例如:("foobar " rlike "foo ")返回 FALSE, ("foobar " rlike "^f.*r$ ")返回 TRUE。 |
A REGEXP B |
字符串 |
与 RLIKE 一样 |
算数运算符
运算符 |
类型 |
说明 |
A + B |
所有数字类型 |
A 和 B 相加。结果的与操作数值有共同类型。例如每一个整数是一个浮点数,浮点数包含整数。所以,一个浮点数和一个整数相加结果也是一个浮点数。 |
A – B |
所有数字类型 |
A 和 B 相减。结果的与操作数值有共同类型。 |
A * B |
所有数字类型 |
A 和 B 相乘,结果的与操作数值有共同类型。需要说明的是,如果乘法造成溢出,将选择更高的类型。 |
A / B |
所有数字类型 |
A 和 B 相除,结果是一个 double(双精度)类型的结果。 |
A % B |
所有数字类型 |
A 除以 B 余数与操作数值有共同类型。 |
A & B |
所有数字类型 |
运算符查看两个参数的二进制表示法的值,并执行按位 “与”操作。两个表达式的一位均为 1 时,则结果的该位为 1。否则,结果的该位为 0。 |
A|B |
所有数字类型 |
运算符查看两个参数的二进制表示法的值,并执行按位 “或”操作。只要任一表达式的一位为 1,则结果的该位为 1。否则,结果的该位为 0。 |
A ^ B |
所有数字类型 |
运算符查看两个参数的二进制表示法的值,并执行按位 “异或”操作。当且仅当只有一个表达式的某位上为 1 时,结果的该位才为 1。否则结果的该位为 0。 |
~A |
所有数字类型 |
对一个表达式执行按位“非”(取反)。 |
逻辑运算符
运算符 |
类型 |
说明 |
A AND B |
布尔值 |
A 和 B 同时正确时,返回 TRUE,否则 FALSE。如果 A 或 B 值为 NULL,返回 NULL。 |
A && B |
布尔值 |
与“A AND B”相同 |
A OR B |
布尔值 |
A 或 B 正确,或两者同时正确返返回 TRUE,否则 FALSE。如果 A 和 B 值同时为 NULL,返回 NULL。 |
A | B |
布尔值 |
与“A OR B”相同 |
NOT A |
布尔值 |
如果 A 为 NULL 或错误的时候返回 TURE,否则返回 FALSE。 |
! A |
布尔值 |
与“NOT A”相同 |
复杂类型函数
函数 |
类型 |
说明 |
map |
(key1, value1, key2, value2, …) |
通过指定的键/值对,创建一个 map。 |
struct |
(val1, val2, val3, …) |
通过指定的字段值,创建一个结构。结构字段名称将 COL1,COL2,… |
array |
(val1, val2, val3, …) |
通过指定的元素,创建一个数组。 |
对复杂类型函数操作
函数 |
类型 |
说明 |
A[n] |
A 是一个数组,n 为 int 型 |
返回数组 A 的第 n 个元素,第一个元素的索引为 0。如果 A 数组为['foo','bar'],则 A[0]返回'foo'和 A[1]返回'bar'。 |
M[key] |
M 是 Map<K, V>,关键 K 型 |
返回关键值对应的值,例如 mapM 为 \{'f' -> 'foo', 'b' -> 'bar', 'all' -> 'foobar'\},则 M['all'] 返回'foobar'。 |
S.x |
S 为 struct |
返回结构 x 字符串在结构 S 中的存储位置。如 foobar \{int foo, int bar\} foobar.foo 的领域中存储的整数。 |
内置函数数学函数
返回类型 |
函数 |
说明 |
BIGINT |
round(double a) |
四舍五入 |
DOUBLE |
round(double a, int d) |
小数部分 d 位之后数字四舍五入,例如 round(21.263,2),返回 21.26 |
BIGINT |
floor(double a) |
对给定数据进行向下舍入最接近的整数。例如 floor(21.2),返回 21。 |
BIGINT |
ceil(double a), ceiling(double a) |
将参数向上舍入为最接近的整数。例如 ceil(21.2),返回 23. |
double |
rand(), rand(int seed) |
返回大于或等于 0 且小于 1 的平均分布随机数(依重新计算而变) |
double |
exp(double a) |
返回 e 的 n 次方 |
double |
ln(double a) |
返回给定数值的自然对数 |
double |
log10(double a) |
返回给定数值的以 10 为底自然对数 |
double |
log2(double a) |
返回给定数值的以 2 为底自然对数 |
double |
log(double base, double a) |
返回给定底数及指数返回自然对数 |
double |
pow(double a, double p) power(double a, double p) |
返回某数的乘幂 |
double |
sqrt(double a) |
返回数值的平方根 |
string |
bin(BIGINT a) |
返回二进制格式 |
string |
hex(BIGINT a) hex(string a) |
将整数或字符转换为十六进制格式 |
string |
unhex(string a) |
十六进制字符转换由数字表示的字符。 |
string |
conv(BIGINT num, int from_base, int to_base) |
将 指定数值,由原来的度量体系转换为指定 的试题体系。例如 CONV(‘a’,16,2),返回。参考:’1010′ http://dev.mysql.com/doc/refman/5.0/en/mat hematical-functions.html#function_conv |
double |
abs(double a) |
取绝对值 |
int double |
pmod(int a, int b) pmod(double a, double b) |
返回 a 除 b 的余数的绝对值 |
double |
sin(double a) |
返回给定角度的正弦值 |
double |
asin(double a) |
返回 x 的反正弦,即是 X。如果 X 是在-1 到 1 的正弦值,返回 NULL。 |
double |
cos(double a) |
返回余弦 |
double |
acos(double a) |
返回 X 的反余弦,即余弦是 X,,如果-1<= A <= 1,否则返回 null. |
int double |
positive(int a) positive(double a) |
返回 A 的值,例如 positive(2),返回 2。 |
int double |
negative(int a) negative(double a) |
返回 A 的相反数,例如 negative(2),返回-2。 |
收集函数
返回类型 |
函数 |
说明 |
int |
size(Map<K.V>) |
返回的 map 类型的元素的数量 |
int |
size(Array<T>) |
返回数组类型的元素数量 |
类型转换函数
返回类型 |
函数 |
说明 |
指定 “type” |
cast(expr as <type>) |
类型转换。例如将字符”1″转换为整数:cast(’1′ as bigint),如果转换失败返回 NULL。 |
日期函数
返回类型 |
函数 |
说明 |
string |
from_unixtime(bigint unixtime[, string format]) |
UNIX_TIMESTAMP 参数表示返回一个值’YYYY- MM – DD HH: MM:SS’或 YYYYMMDDHHMMSS.uuuuuu 格式,这取决于是否 是在一个字符串或数字语境中使用的功能。该值表示在当前的时区。 |
bigint |
unix_timestamp() |
如果不带参数的调用,返回一个 Unix 时间戳(从’1970- 01 – 0100:00:00′到现在的 UTC 秒数)为无符号整数。 |
bigint |
unix_timestamp(string date) |
指定日期参数调用 UNIX_TIMESTAMP(),它返回参数值’1970- 01 – 0100:00:00′到指定日期的秒数。 |
bigint |
unix_timestamp(string date, string pattern) |
指定时间输入格式,返回到 1970 年秒数: unix_timestamp(’2009-03-20′, ‘yyyy-MM-dd’) = 1237532400 |
string |
to_date(string timestamp) |
返回时间中的年月日: to_date(“1970-01-01 00:00:00″) = “1970-01-01″ |
string |
to_dates(string date) |
给定一个日期 date,返回一个天数(0 年以来的天数) |
int |
year(string date) |
返回指定时间的年份,范围在 1000 到 9999,或为”零”日期的 0。 |
int |
month(string date) |
返回指定时间的月份,范围为 1 至 12 月,或 0 一个月的一部分,如’0000-00-00′或’2008-00-00′的日期。 |
int |
day(string date) dayofmonth(date) |
返回指定时间的日期 |
int |
hour(string date) |
返回指定时间的小时,范围为 0 到 23。 |
int |
minute(string date) |
返回指定时间的分钟,范围为 0 到 59。 |
int |
second(string date) |
返回指定时间的秒,范围为 0 到 59。 |
int |
weekofyear(string date) |
返回指定日期所在一年中的星期号,范围为 0 到 53。 |
int |
datediff(string enddate, string startdate) |
两个时间参数的日期之差。 |
int |
date_add(string startdate, int days) |
给定时间,在此基础上加上指定的时间段。 |
int |
date_sub(string startdate, int days) |
给定时间,在此基础上减去指定的时间段。 |
条件函数
返回类型 |
函数 |
说明 |
T |
if(boolean testCondition, T valueTrue, T valueFalseOrNull) |
判断是否满足条件,如果满足返回一个值,如果不满足则返回另一个值。 |
T |
COALESCE(T v1, T v2, …) |
返回一组数据中,第一个不为 NULL 的值,如果均为 NULL,返回 NULL。 |
T |
CASE a WHEN b THEN c [WHEN d THEN e]* [ELSE f] END |
当 a=b 时,返回 c;当 a=d 时,返回 e,否则返回 f。 |
T |
CASE WHEN a THEN b [WHEN c THEN d]* [ELSE e] END |
当值为 a 时返回 b,当值为 c 时返回 d。否则返回 e。 |
字符函数
返回类型 |
函数 |
说明 |
int |
length(string A) |
返回字符串的长度 |
string |
reverse(string A) |
返回倒序字符串 |
string |
concat(string A, string B…) |
连接多个字符串,合并为一个字符串,可以接受任意数量的输入字符串 |
string |
concat_ws(string SEP, string A, string B…) |
链接多个字符串,字符串之间以指定的分隔符分开。 |
string |
substr(string A, int start) substring(string A, int start) |
从文本字符串中指定的起始位置后的字符。 |
string |
substr(string A, int start, int len) substring(string A, int start, int len) |
从文本字符串中指定的位置指定长度的字符。 |
string |
upper(string A) ucase(string A) |
将文本字符串转换成字母全部大写形式 |
string |
lower(string A) lcase(string A) |
将文本字符串转换成字母全部小写形式 |
string |
trim(string A) |
删除字符串两端的空格,字符之间的空格保留 |
string |
ltrim(string A) |
删除字符串左边的空格,其他的空格保留 |
string |
rtrim(string A) |
删除字符串右边的空格,其他的空格保留 |
string |
regexp_replace(string A, string B, string C) |
字符串 A 中的 B 字符被 C 字符替代 |
string |
regexp_extract(string subject, string pattern, int index) |
通过下标返回正则表达式指定的部分。 regexp_extract(‘foothebar’, ‘foo(.*?)(bar)’, 2) returns ‘bar.’ |
string |
parse_url(string urlString, string partToExtract [, string keyToExtract]) |
返回 URL 指定的部分。 parse_url(‘http://facebook.com/path1/p.ph p?k1=v1&k2=v2#Ref1′, ‘HOST’) 返回:’facebook.com’ |
string |
get_json_object(string json_string, string path) |
select a.timestamp, get_json_object(a.appevents, ‘$.eventid’), get_json_object(a.appenvets, ‘$.eventname’) from log a; |
string |
space(int n) |
返回指定数量的空格 |
string |
repeat(string str, int n) |
重复 N 次字符串 |
int |
ascii(string str) |
返回字符串中首字符的数字值 |
string |
lpad(string str, int len, string pad) |
返回指定长度的字符串,给定字符串长度 小于指定长度时,由指定字符从左侧填补。 |
string |
rpad(string str, int len, string pad) |
返回指定长度的字符串,给定字符串长度 小于指定长度时,由指定字符从右侧填补。 |
array |
split(string str, string pat) |
将字符串转换为数组。 |
int |
find_in_set(string str, string strList) |
返回字符串 str 第一次在 strlist 出现的位 置。如果任一参数为 NULL,返回 NULL;如果第一个参数包含逗号,返回 0。 |
array<array <string>> |
sentences(string str, string lang, string locale) |
将字符串中内容按语句分组,每个单词间以逗号分隔,最后返回数组。 例如 sentences(‘Hello there! How are you?’) 返 |
回:( (“Hello”, “there”), (“How”, “are”, “you”) ) |
||
array<struct <string,dou ble>> |
ngrams(array<array<string>>, int N, int K, int pf) |
SELECT ngrams(sentences(lower(tweet)), 2, 100 [, 1000]) FROM twitter; |
array<struct <string,dou ble>> |
context_ngrams(array<array<str ing>>, array<string>, int K, int pf) |
SELECT context_ngrams(sentences(lower(tweet)), array(null,null), 100, [, 1000]) FROM twitter; |
内置的聚合函数(UDAF)
返回类型 |
函数 |
说明 |
bigint |
count(*) , count(expr), count(DISTINCT expr[, expr_., expr_.]) |
返回记录条数。 |
double |
sum(col), sum(DISTINCT col) |
求和 |
double |
avg(col), avg(DISTINCT col) |
求平均值 |
double |
min(col) |
返回指定列中最小值 |
double |
max(col) |
返回指定列中最大值 |
double |
var_pop(col) |
返回指定列的方差 |
double |
var_samp(col) |
返回指定列的样本方差 |
double |
stddev_pop(col) |
返回指定列的偏差 |
double |
stddev_samp(col) |
返回指定列的样本偏差 |
double |
covar_pop(col1, col2) |
两列数值协方差 |
double |
covar_samp(col1, col2) |
两列数值样本协方差 |
double |
corr(col1, col2) |
返回两列数值的相关系数 |
double |
percentile(col, p) |
返回数值区域的百分比数值点。0<=P<=1,否则返回 NULL,不支持浮点型数值。 |
array<double> |
percentile(col, array(p~1,,\ [, p,,2,,]…)) |
返回数值区域的一组百分比值分别对应的数值点。0<=P<=1,否则返回 NULL,不支持浮点型数值。 |
double |
percentile_approx(col , p[, B]) |
Returns an approximate p^th^ percentile of a numeric column (including floating point types) in the group. The B parameter controls approximation accuracy at the cost of memory. Higher values yield better approximations, and the default is 10,000. When the number of distinct values in col is smaller than B, this gives an exact percentile value. |
array<double> |
percentile_approx(col , array(p~1,, [, p,,2_]…) [, B]) |
Same as above, but accepts and returns an array of percentile values instead of a single one. |
array<struct\{‘x ’,'y’\}> |
histogram_numeric(c ol, b) |
Computes a histogram of a numeric column in the group using b non-uniformly spaced bins. The output is an array of size b of double-valued (x,y) coordinates that represent the bin centers and heights |
array |
collect_set(col) |
返回无重复记录 |
内置表生成函数(UDTF)
返回类型 |
函数 |
说明 |
数组 |
explode(array<TYPE> a) |
数组一条记录中有多个参数,将参数拆分,每个参数生成一列。 |
|
json_tuple |
get_json_object 语句:select a.timestamp, get_json_object(a.appevents, ‘$.eventid’), get_json_object(a.appenvets, ‘$.eventname’) from log a; json_tuple 语句: select a.timestamp, b.* from log a lateral view json_tuple(a.appevent, ‘eventid’, ‘eventname’) b as f1, f2 |
自定义函数
自定义函数包括三种UDF、UDAF、UDTF
UDF(User-Defined-Function) 一进一出
UDAF(User- Defined Aggregation Funcation) 聚集函数,多进一出。如 Count/max/min
UDTF(User-Defined Table-GeneratingFunctions)  一进多出,如 lateral view explore()
使用方式 :在 HIVE 会话中add 自定义函数的 jar 文件,然后创建 function 继而使用函数
UDF 开发
1) UDF 函数可以直接应用于 select 语句,对查询结构做格式化处理后,再输出内容。
2) 编写 UDF 函数的时候需要注意一下几点:
a) 自定义 UDF 需要继承 org.apache.hadoop.hive.ql.UDF。
b) 需要实现 evaluate 函数,evaluate 函数支持重载。
3) 步骤
a) 把程序打包放到目标机器上去;
b) 进入 hive 客户端,添加 jar 包:hive>addjar /run/jar/udf_test.jar;
c) 创建临时函数:hive>CREATE TEMPORARY FUNCTIONadd_example AS 'hive.udf.Add';
d) 查询 HQL 语句:
SELECT add_example(8, 9) FROM scores;
SELECT add_example(scores.math, scores.art) FROM scores;
SELECT add_example(6, 7, 8, 6.8) FROM scores;
e) 销毁临时函数:hive> DROP TEMPORARY FUNCTIONadd_example;
UDAF自定义集函数
多行进一行出,如sum()、min(),用在 group by 时
1) 必须继承
org.apache.hadoop.hive.ql.exec.UDAF(函数类继承) org.apache.hadoop.hive.ql.exec.UDAFEvaluator
(内部类 Evaluator 实现 UDAFEvaluator接口)
2) Evaluator 需要实现init、iterate、terminatePartial、merge、terminate 这几个函数 init():类似于构造函数,用于 UDAF 的初始化 iterate():接收传入的参数,并进行内部的轮转,返回 boolean terminatePartial():无参数,其为 iterate函数轮转结束后,返回轮转数据,类似于 hadoop 的Combiner
merge():接收 terminatePartial 的返回结果,进行数据 merge 操作,其返回类型为boolean
terminate():返回最终的聚集函数结果
3) 开发一个功能同:
Oracle 的 wm_concat()函数 Mysql的 group_concat()
Hive UDF 的数据类型
案例-输出数据时部分内容显示为“*”
package com.sxt.hive.udf;
import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; public class TestUDF extends UDF{ //输出信息时部分内容用*代替 public Text evaluate(final Text s) { if (s == null) { return null; } String str = s.toString().substring(0, 3) + "***"; return new Text(str); } } 步骤: 1. 打成 jar 包 2. 上传到 Hive 客户端 3. hive> add jar /root/TestUDF.jar; Added [/root/TestUDF.jar] to class path Added resources: [/root/TestUDF.jar] 4. hive> CREATE TEMPORARY FUNCTION display AS 'com.sxt.hive.udf.TestUDF'; hive> select id,name,display(name) from person0; OK 1 Jed Jed*** 2 Tom Tom*** 3 Cat Cat*** 5. 销毁临时函数 hive> DROP TEMPORARY FUNCTION display; |
案例
基站掉话率给定 50M 数据,部分数据如下: 字段说明:
record_time:通话时间imei:基站编号 cell:手机编号 drop_num:掉话的秒数
duration:通话持续总秒数要求:找出掉线率最高的前 10 基站
hive>create table cell_monitor( record_time string, imei string, cell string, ph_num int, call_num int, drop_num int, duration int, drop_rate double, net_type string, erl string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE; hive>load data local inpath "/root/hivecase1_data" into table cell_monitor; hive>select * from cell_monitor limit 5; 2011-07-13 00:00:00+08 356966 29448-37062 0 0 0 0 0.0 G |
0 |
2011-07-13 00:00:00+08 352024 29448-51331 0 0 0 0 0.0 G |
0 |
2011-07-13 00:00:00+08353736 29448-51331 0 0 0 0 0.0 G 0 2011-07-13 00:00:00+08 353736 29448-51333 0 0 0 0 0.0 G 0 2011-07-13 00:00:00+08 351545 29448-51333 0 0 0 0 0.0 G 0 建结果表 hive>create table cell_result( imei string, total_call_num int, total_drop_num int, d_rate double ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS TEXTFILE; hive>from cell_monitor cm insert overwrite table cell_result select cm.imei ,sum(cm.drop_num),sum(cm.duration),sum(cm.drop_num)/sum(cm.duration) d_rate group by cm.imei sort by d_rate desc; hive>select * from cell_result limit 10; 639876 1 734 0.0013623978201634877 356436 1 1028 9.727626459143969E-4 351760 1 1232 8.116883116883117E-4 368883 1 1448 6.906077348066298E-4 358849 1 1469 6.807351940095302E-4 358231 1 1613 6.199628022318661E-4 863738 2 3343 5.982650314089142E-4 865011 1 1864 5.36480686695279E-4 862242 1 1913 5.227391531625719E-4 350301 2 3998 5.002501250625312E-4 |
WordCount
hive>create table wordcount (line string); hive>load data local inpath "/root/wordcount_data" into table wordcount; hive>select * from wordcount; C C++ Java MySQL Oracle Spring SpringMVC Hibernate Struts2 SpringMVC Hibernate Hadoop Hive MapReduce Spring SpringMVC Java MySQL Oracle C C++ Java MySQL Oracle |
Struts2 SpringMVC Hibernate Hadoop Hive MapReduce hive> select split(line,' ') from wordcount; ["C","C++","Java","MySQL","Oracle"] ["Spring","SpringMVC","Hibernate",""] ["Struts2","SpringMVC","Hibernate"] ["Hadoop","Hive","MapReduce","Spring","SpringMVC"] ["Java","MySQL","Oracle","C","C++","Java","MySQL","Oracle"] ["Struts2","SpringMVC","Hibernate"] ["Hadoop","Hive","MapReduce"] hive> select explode(split(line,' ')) from wordcount; OK C C++ Java MySQL Oracle Spring SpringMVC Hibernate Struts2 SpringMVC Hibernate Hadoop Hive MapReduce Spring SpringMVC Java MySQL Oracle C C++ Java MySQL Oracle Struts2 SpringMVC Hibernate Hadoop Hive MapReduce |
hive> createtable count_result(word string,num int);
hive> from(select explode(split(line,' ')) as word from wordcount) w insert into tablecount_result select w.word,count(1) as num group by w.word;
hive> select *from count_result;
OK
C 2
C++ 2
Hadoop 2
Hibernate 3
Hive 2
Java 3
MapReduce 2
MySQL 3
Oracle 3
Spring 2
SpringMVC 4
Struts2 2
Hive 参数和变量
hive当中的参数、变量,都是以命名空间开头
命名空间 |
读写权限 |
含义 |
hiveconf |
可读写 |
hive-site.xml 当中的各配置变量 例:hive --hiveconf hive.cli.print.header=true |
system |
可读写 |
系统变量,包含 JVM 运行参数等 例:system:user.name=root |
env |
只读 |
环境变量 例:env:JAVA_HOME |
hivevar |
可读写 |
例:hive -d val=key |
通过${}方式进行引用,其中 system、env 下的变量必须以前缀开头
hive 参数设置方式
1. 修改配置文件 ${HIVE_HOME}/conf/hive-site.xml
2. 启动 hive cli 时,通过--hiveconf key=value 的方式进行设置(临时生效)
例:hive --hiveconf hive.cli.print.header=true
显示表头
[root@node03 ~]#hive --hiveconf hive.cli.print.header=true hive> select * from count_resultlimit 2;
count_result.wordcount_result.num
C 2
C++ 2
临时生效
[root@node03 ~]#hive -d val=test; hive> create table ${val} (id int,name string); hive>show tables; test
3.进入 cli 之后,通过使用set 命令设置(临时生效)
hive set 命令在 hiveCLI 控制台可以通过 set 对 hive 中的参数进行查询、设置。
set 设置:
set hive.cli.print.header=true;
set 查看某个配置的值:
set hive.cli.print.header
set 查看全部配置项: sethive 参数初始化配置文件:当前用户家目录下的.hiverc 文件,如: ~/.hiverc,如果没有,可直接创建该文件,将
需要设置的参数写到该文件中,hive 启动运行时,会加载改文件中的配置。
hive 历史操作命令集:
~/.hivehistory
hive> set hive.cli.print.header=true; hive> select * from count_result limit 3; count_result.word count_result.num C 2 C++ 2 hive> set hive.cli.print.header; hive.cli.print.header=true 永久生效 [root@node03 ~]# vi .hiverc set hive.cli.print.header = true; [root@node03 ~]# tail -5 .hivehistory select * from cell_result; select * from cell_result limit 2; select * from count_result limit 2; quit; |
Hive 动态分区
建表时指出分区字段,但不给值,导入数据时 hive 根据分区字段的值自动创建分区。
开启动态分区需要修改一些配置:是否开启动态分区,默认:false
set hive.exec.dynamic.partition=true;
动态分区模式,默认:strict:严格模式,至少有一个分区列是静态分区
sethive.exec.dynamic.partition.mode=nostrict;
相关参数:每一个执行 mr 节点上,允许创建的动态分区的最大数量(100)
sethive.exec.max.dynamic.partitions.pernode;
所有执行 mr 节点上,允许创建的所有动态分区的最大数量(1000)
set hive.exec.max.dynamic.partitions;
所有的 mr job 允许创建的文件的最大数量(100000)
set hive.exec.max.created.files;
hive> set hive.exec.dynamic.partition=true; hive> set hive.exec.dynamic.partition.mode=nostrict; hive> create table part0 ( id int, name string ) PARTITIONED BY (sex string) ROW FORMAT DELIMITED FIELDS TERMINATED BY ','; hive> desc part0; col_name data_type comment id int name string sex string # Partition Information # col_name data_type comment sex string 导入两个分区的数据 hive> load data local inpath '/root/part0_data' into table part0 PARTITION (sex='1'); hive> load data local inpath '/root/part0_data' into table part0 PARTITION (sex='2'); hive> select * from part0; part0.id part0.name part0.sex 1 Jed 1 2 Tom 1 3 Cat 1 1 Jed 2 |
2 Tom 2 3 Cat 2 创建一个和 part0 表机构完全相同的表 part1 hive> create table part1 like part0; 给 part1 导入数据,使用动态分区 hive> from part0 insert into table part1 partition (sex) select *; hive> select * from part1; part1.id part1.name part1.sex 1 Jed 1 2 Tom 1 3 Cat 1 1 Jed 2 2 Tom 2 3 Cat 2 |
使用动态分区导入数据时,不使用 load,因为 load 必须指定分区的值,应该使用 from+select 方式。
Hive 分桶
分桶表是对列值取哈希值的方式,将不同数据放到不同文件中存储。对于 hive 中每一
个表、分区都可以进一步进行分桶。由列的哈希值除以桶的个数来决定每条数据划分在哪个桶中。比分区更加细粒度。
适用场景:数据抽样( sampling )、map-join
开启分桶支持:
set hive.enforce.bucketing=true;
默认:false。设置为true 之后,mr 运行时会根据 bucket 的个数自动分配 reducetask
个数。(用户也可以通过 mapred.reduce.tasks 自己设置 reduce任务个数,但分桶时不推荐使用)注意:一次作业产生的桶(文件数量)和reduce task 个数一致。
hive> sethive.enforce.bucketing=true;
创建分桶表
hive> CREATETABLE bucket(id int, name string, age int)
CLUSTERED BY(age) INTO 4 BUCKETS
ROW FORMATDELIMITED FIELDS TERMINATED BY ',';
查看表结构(比 desc table;更详细)
hive> descformatted bucket;
7 |
Hadoop 77 |
3 |
Dog 33 |
Hive Lateral View
LateralView 用于和 UDTF 函数(explode、split)结合来使用。首先通过UDTF 函数拆分成多行,再将多行结果组合成一个支持别名的虚拟表。主要解决在 select 使用 UTF 做查询过程中,查询只能包含单个 UDTF,不能包含其他字段、以及多个UDTF 的问题。
语法:
LATERAL VIEW udtf(expression) tableAliasAS columnAlias (',' columnAlias)
hive> select * from person0; person0.id person0.name person0.hobbies person0.address 1 Jed ["book","lol"] {"beijing":"chaoyang"} 2 Tom ["book","lol","sports"] {"beijing":"chaoyang","shanghai":"pudong"} 3 Cat ["book","lol","sports","music"] {"beijing":"chaoyang","shanghai":"pudong","shanxi":"taiyuan"} hive> select explode(hobbies) from person0; col book lol book lol sports book lol sports music hive> select explode(address) from person0; key value beijing chaoyang beijing chaoyang shanghai pudong beijing chaoyang shanghai pudong shanxi taiyuan explode 只能支持查询一个字段 hive> select explode(address),id from person0; FAILED: SemanticException 1:24 Only a single expression in the SELECT clause is supported with UDTF's. Error encountered near token 'i d'hive> select explode(address),explode(hobbies) from person0; |
FAILED:SemanticException 1:24 Only a single expression in the SELECT clause issupported with UDTF's. Error encountered near token 'h obbies'
例子:统计表中有多少种 hobby 和 city
hive> selectcount(distinct(myCol1)) , count(distinct(myCol2)) from person0
LATERAL VIEWexplode(hobbies) myTable1 AS myCol1
LATERAL VIEWexplode(address) myTable2 AS myCol2, myCol3;
_c0 _c1
4 3
Hive View 视图
和关系型数据库中的普通视图一样,hive 也支持视图
特点:
不支持物化视图、只能查询,不能做加载数据操作;视图的创建,只是保存一份元数据,查询视图时才执行对应的子查询;
view 定义中若包含了 ORDER BY/LIMIT 语句,当查询视图时也进行 ORDER BY/LIMIT 语
句操作,view 当中定义的优先级更高,view 支持迭代视图。
View 语法:创建视图
CREATE VIEW [IF NOT EXISTS][db_name.]view_name
[(column_name [COMMENT column_comment], ...) ]
[COMMENT view_comment]
[TBLPROPERTIES (property_name = property_value, ...)]
ASSELECT ... ;
查询视图
select colums from view;
删除视图
DROP VIEW [IF EXISTS] [db_name.]view_name;
Hive 索引
目的:优化查询以及检索性能
创建索引:
create index t1_index on tableperson0(name)
as'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild in tablet1_index_table;
as:指定索引器;
in table:指定索引表,若不指定默认生成在 default_person0_t1_index_表中
create index t1_index on tableperson0(name) as'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferredrebuild;
查询索引
show index on person0;
重建索引(建立索引之后必须重建索引才能生效)
ALTER INDEX t1_index ON person0 REBUILD;
删除索引
DROP INDEX IF EXISTS t1_index ON person0;
Hive> create index t1_index on table person0(name) as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild in table t1_index_table; hive> show tables; person0 t1_index_table hive> show index on person0; t1_index person0 name t1_index_table compact hive> ALTER INDEX t1_index ON person0 REBUILD; hive> select * from t1_index_table; Cat hdfs://mycluster/user/hive/warehouse/person0/person0_data [87] Jed hdfs://mycluster/user/hive/warehouse/person0/person0_data [0] Tom hdfs://mycluster/user/hive/warehouse/person0/person0_data [32] |
Hive 运行方式
命令行方式 cli:控制台模式 metastore hive hiveserver2 beeline
脚本运行方式(实际生产环境中用最多)
JDBC 方式:hiveserver2 web GUI 接口(hwi、hue 等)
命令行模式
与 HDFS 交互(比在 Linux中快,因为已经获得连接)
hive> dfs -ls/; Found 3 items drwxr-xr-x - rootsupergroup 0 2017-07-11 19:58/psn6 drwxr-xr-x - root supergroup 0 2017-07-11 15:31 /tmpdrwxr-xr-x - root supergroup 0 2017-07-11 17:22 /user
与 Linux 交互(Linux命令以!开头)
hive> ! pwd;
/root
脚本方式运行
查询 [root@node03 ~]# hive -e "select * from wordcount limit 3"; 17/07/12 17:35:43 WARN conf.HiveConf: HiveConf of name hive.metastore.local does not exist Logging initialized using configuration in jar:file:/opt/sxt/apache-hive-1.2.1-bin/lib/hivecommon-1.2.1.jar!/hive-log4j.properties OK C C++ Java MySQL Oracle Spring SpringMVC Hibernate Struts2 SpringMVC Hibernate Time taken: 1.831 seconds, Fetched: 3 row(s) 静默执行,只返回结果,不返回其他信息 [root@node03 ~]# hive -S -e "select * from wordcount limit 3"; 17/07/12 17:39:18 WARN conf.HiveConf: HiveConf of name hive.metastore.local does not exist C C++ Java MySQL Oracle Spring SpringMVC Hibernate Struts2 SpringMVC Hibernate 查询结果保存到文件中 [root@node03 ~]# hive -e "select * from wordcount limit 1" > result; [root@node03 ~]# vi result C C++ Java MySQL Oracle 执行指定文件中的 sql 语句(有几条执行几条,顺序执行) [root@node03 ~]# vi sql select * from wordcount limit 1; [root@node03 ~]# hive -f sql C C++ Java MySQL Oracle 执行指定文件中的 sql 语句,执行完后进入 hive 客户端 |
[root@node03 ~]# hive -i sql hive> 在 hive 客户端中执行 Linux 中的文件 hive> source /root/sql; C C++ Java MySQL Oracle |
web GUI 接口-hwi
搭建步骤
1. 把 apache-hive-*-src/hwi/web/下的所有文件打成 war 包
Microsoft Windows [版本 10.0.14393]
(c) 2016 Microsoft Corporation。保留所有权利。
C:\Users\Jed>e:
E:\>cd E:\package\hive-1.2.1-src\apache-hive-1.2.1-src\hwi\web
E:\package\hive-1.2.1-src\apache-hive-1.2.1-src\hwi\web>jar-cvf hive-hwi.war *
war 包在亚索的当前目录生成
2. 把 war 包上传到$HIVE_HOME/lib/下(服务端)
3. 把 JAVA_HOME/lib/下的 tool.jar 拷贝到$HIVE_HOME/lib/下
[root@node04 ~]# cp /usr/java/jdk1.7.0_67/lib/tools.jar/opt/sxt/apache-hive-1.2.1-bin/lib/
4. 修改 hive-site.xml,添加如下配置
<property>
<name>hive.hwi.listen.host</name>
<value>0.0.0.0</value>
</property>
<property>
<name>hive.hwi.listen.port</name>
<value>9999</value>
</property>
<property>
<name>hive.hwi.war.file</name>
<value>lib/hive-hwi.war</value>
</property>
5. 启动 hwi 服务
[root@node04 conf]# hive --service hwi
6. 访问浏览器
创建查询:
结果:
Hive 权限
三种授权模型:
1. Storage Based Authorization inthe Metastore Server
基于存储的授权:可以对 Metastore 中的元数据进行保护,但是没有提供更加细粒度
的访问控制(例如:列级别、行级别)。
2. SQL Standards BasedAuthorization in HiveServer2
基于 SQL 标准的 Hive授权:完全兼容 SQL 的授权模型,推荐使用该模式。除支持对于
用户的授权认证,还支持角色 role 的授权认证。role 可理解为是一组权限的集合,通过 role 为用户授权。一个用户可以具有一个或多个角色。默认包含两种种角色:public、 admin。
基于 SQL 标准的 Hive 授权模型的限制:
1) 启用当前认证方式之后,dfs, add, delete, compile, reset 等命令被禁用。
2) 通过 set 命令设置 hive configuration 的方式限制某些用户使用。(可通过修改配置文件 hive-site.xml 中 hive.security.authorization.sqlstd.confwhitelist 进行配置)
3) 添加、删除函数以及宏的操作,仅为具有 admin 的用户开放。
4) 用户自定义函数(开放支持永久的自定义函数),可通过具有 admin 角色的用户创建,其他用户都可以使用。
5) Transform 功能被禁用。
3. Default HiveAuthorization (Legacy Mode)
hive 默认授权:设计目的仅仅只是为了防止用户产生误操作,而不是防止恶意用户访
问未经授权的数据。
开启基于 SQL 标准的授权模型1) 在 hive 服务端添加如下配置
[root@node04 ~]#vi /opt/sxt/apache-hive-1.2.1-bin/conf/hive-site.xml
<property>
<name>hive.security.authorization.enabled</name>
<value>true</value>
</property>
<property>
<name>hive.server2.enable.doAs</name>
<value>false</value>
</property>
<!--设置 root用户为admin 角色-->
<property>
<name>hive.users.in.admin.role</name>
<value>root</value>
</property>
<property>
<name>hive.security.authorization.manager</name> <value> org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory </value> </property> <property> <name>hive.security.authenticator.manager</name> <value>org.apache.hadoop.hive.ql.security.SessionStateUserAuthenticator</value> </property> 2) 服务端启动 hiveserver2 [root@node04 ~]# hiveserver2 3) 客户端通过 beeline 进行连接 root@node03 ~]# beeline -u jdbc:hive2://node04:10000 -n root 虽然在服务端配置文件中指定了 root 的角色是 admin,但在客户端还需要用 set 命令指定,否则无法创建角色 0: jdbc:hive2://node04:10000> create role role1; Error: Error while processing statement: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. Current u ser : root is not allowed to add roles. User has to belong to ADMIN role and have it as current role, for this action. (state=08S01,code=1) 查看当前具有的角色 0: jdbc:hive2://node04:10000> show current roles; 设置角色 0: jdbc:hive2://node04:10000> set role admin; 0: jdbc:hive2://node04:10000> show current roles; 创建角色 0: jdbc:hive2://node04:10000> create role role1; 查看所有存在的角色 0: jdbc:hive2://node04:10000> show roles; |
priv_type [, priv_type ] ... ON table_or_view_name FROM principal_specification [, principal_specification] ... ; 查看某个用户、角色的权限: SHOW GRANT [principal_name] ON (ALL| ([TABLE] table_or_view_name);
查看属于某种角色的用户、角色列表 SHOW PRINCIPALS role_name; 删除角色 0: jdbc:hive2://node04:10000> drop role role1; |
Hive 优化
hive 核心思想:把 Hive SQL 当做 Mapreduce程序去优化。以下 SQL 不会转为
Mapreduce 来执行: select 仅查询本表字段; where 仅对本表字段做条件过滤。
explain 命令可以显示执行计划:EXPLAIN [EXTENDED] query; EXTENDED 可以看到更详细的信息。
本地模式提高执行效率
本地模式:mapreduce 任务运行在一台节点上,该节点把需要的资源从其他机器copy 过来
集群模式:
mapreduce 任务在 hadoop集群中执行开启本地模式:
set hive.exec.mode.local.auto=true;
注意:
hive.exec.mode.local.auto.inputbytes.max 默认值为 128M,表示加载文件的最大值,若
大于该配置仍会以集群方式来运行
查询的数据在数据量不大的表中,这种情况使用本地模式,数据量大时使用集群模式
并行计算
hive 执行 sql 默认是顺序执行,如下 sql 如果使用并行计算会大大提高效率,但是集群
压力也增大:
select wc.col1,bk.col2 from
(select count(*) as col1 from wordcount)wc,
(select count(*) as col2 from bucket) bk;
两条子查询可以使用并行计算
通过设置以下参数开启并行模式: sethive.exec.parallel=true;
注意:
hive.exec.parallel.thread.number
代表一次 SQL 计算中允许并行执行的job 个数的最大值严格模式
查询限制:
1) 对于分区表,必须添加 where 对于分区字段的条件过滤;
2) order by 语句必须包含 limit输出限制; 3) 限制执行笛卡尔积的查询。
笛卡尔集中的记录不一定正确,为了避免笛卡尔集可以在 WHERE 中加入有效的连接条
件,实际运行环境下应该避免使用笛卡尔全集。
通过设置以下参数开启严格模式:
set hive.mapred.mode=strict;(默认为:nonstrict非严格模式)
Hive 排序
Order By
对于查询结果做全排序,只允许有一个 reduce 处理。当数据量较大时,应慎用。严格
模式下,必须结合 limit 来使用
Sort By
对于单个 reduce 的数据进行排序
Distribute By
分区排序,经常和 Sort By 结合使用
Cluster By
相当于 Sort By + Distribute By,Cluster By 不能通过 asc、desc 的方式指定排序规则;
可通过 distribute by column sort by column asc|desc 的方式结合使用。
Hive join
Join 计算时,将小表(驱动表)放在 join 的左边
Map Join:在 Map 端完成 Join(避免数据倾斜)两种实现方式:
1) SQL 方式,在 SQL语句中添加 MapJoin 标记(mapjoin hint)语法:
SELECT /*+ MAPJOIN(smallTable) */ smallTable.key, bigTable.value
FROM smallTable JOIN bigTable ON smallTable.key = bigTable.key;
2) 开启自动的 MapJoin 通过修改以下配置启用自动的 mapjoin: sethive.auto.convert.join = true;
该参数为 true 时,Hive 自动对左边的表统计量,如果是小表就加入内存,即对小表使用 Map join
相关配置参数:
hive.mapjoin.smalltable.filesize;
大表小表判断的阈值,如果表的大小小于该值则会被加载到内存中运行 hive.ignore.mapjoin.hint;
默认值:true;是否忽略mapjoin hint 即 mapjoin 标记
hive.auto.convert.join.noconditionaltask;
默认值:true;将普通的 join 转化为普通的 mapjoin时,是否将多个 mapjoin 转化为一个 mapjoin
hive.auto.convert.join.noconditionaltask.size;
最多可以把几个mapjoin 转化为一个 mapjoin
Map-Side 聚合
通过设置以下参数开启在 Map 端的聚合:set hive.map.aggr=true;
相关配置参数:
hive.groupby.mapaggr.checkinterval:
map 端 groupby 执行聚合时处理的多少行数据(默认:100000)
hive.map.aggr.hash.min.reduction:
进行聚合的最小比例,预先对 100000 条数据做聚合,若聚合之后的数据量/100000 的
值大于该配置 0.5,则不会聚合
hive.map.aggr.hash.percentmemory: map 端聚合使用的内存的最大值
hive.map.aggr.hash.force.flush.memory.threshold:
map 端做聚合操作时 hash表的最大可用内存,大于该值则会触发 flush,溢写到磁盘 hive.groupby.skewindata
是否对 GroupBy 产生的数据倾斜做优化,默认为 false
控制 Hive 中 Map 以及 Reduce的数量
Map 数量相关的参数:
mapred.max.split.size
一个 split 的最大值,即每个 map 处理文件的最大值 mapred.min.split.size.per.node
一个节点上 split 的最小值
mapred.min.split.size.per.rack
一个机架上 split 的最小值
Reduce 数量相关的参数:
mapred.reduce.tasks
强制指定 reduce 任务的数量
hive.exec.reducers.bytes.per.reducer每个 reduce 任务处理的数据量 hive.exec.reducers.max
每个任务最大的 reduce 数
JVM 重用
适用场景:
1) 小文件个数过多
2) task 个数过多
频繁的申请资源,释放资源降低了执行效率
通过 set mapred.job.reuse.jvm.num.tasks=n; (n 为 task 插槽个数)来设置,道理与
“池”类似。
缺点:
设置开启之后,task 插槽会一直占用资源,不论是否有 task 运行,直到所有的task 即整个 job 全部执行完成时,才会释放所有的 task 插槽资源。