Hive函数、外部表和分区表
目录
- 1. Hive自定义函数
- 1.1 pom.xml中依赖配置
- 1.2 Hive自定义函数示例代码
- 1.3 打包并演示
- 2. 外部表
- 3. 分区表
- 参考
1. Hive自定义函数
Hive中简单的自定义函数需要继承org.apache.hadoop.hive.ql.udf.generic.GenericUDF
,并且实现其中的三个方法:
方法 | 功能 |
---|---|
public ObjectInspector initialize(ObjectInspector[] arguments) | 初始化Hive自定义函数,并且检查参数的类型、数量 |
public Object evaluate(DeferredObject[] arguments) | Hive自定义函数要实现的功能 |
public String getDisplayString(String[] children) | 解释Hive自定义函数功能的字符串 |
下面我将给出一个简单的Hive自定义函数,该函数的功能是在string类型前加入”Hello, "字符串。
1.1 pom.xml中依赖配置
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>4.0.1</version>
</dependency>
</dependencies>
1.2 Hive自定义函数示例代码
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
public class App extends GenericUDF {
private PrimitiveObjectInspector inputIO;
@Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
if (arguments.length != 1 || !arguments[0].getTypeName().equals("string")) {
throw new UDFArgumentException("only accept one string argument!");
}
inputIO = (PrimitiveObjectInspector) arguments[0];
return PrimitiveObjectInspectorFactory.javaStringObjectInspector;
}
@Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
if (arguments[0] == null) {
return null;
}
String input = inputIO.getPrimitiveJavaObject(arguments[0].get()).toString();
return "Hello, " + input;
}
@Override
public String getDisplayString(String[] children) {
return "Hello, " + children[0];
}
}
1.3 打包并演示
在maven项目路径下用mvn clean package
打包,用cp target/string-ext-1.0.jar ~/hive-4.0.1/lib
将自定义函数的jar包存放到hive包路径下。
命令:
beeline -u 'jdbc:hive2://172.18.0.2' -n root
add jar /root/hive-4.0.1/lib/string-ext-1.0.jar;
create temporary function stringext as 'com.mengsui.App';
select fname, stringext(lname) as hello_lname from users;
2. 外部表
在Hive中创建表时,默认情况下Hive负责管理数据,这意味着Hive把数据移入它的仓库目录,这种表叫做内部表或者托管表。而另一种选择是创建一个外部表,这意味着Hive到仓库目录外的位置访问数据。
由于加载数据就是文件系统中的文件移动或者文件重命名,因此它的执行速度很快。即使是内部表,Hive也不检查表目录中的文件是否与表所声明的模式相符合。如果有数据和模式不匹配,只有在查询时才会知道。对于内部表而言,丢弃某个表,它的元数据和数据都会被删除。
对于外部表而言,外部表需要手动控制数据的创建和删除。外部数据的位置需要在创建表的时候进行指明。创建外部表的命令:create external table name (pattern) location hdfs_path;
create external table ext_users (user_id int, fname string, lname string) row format delimited fields terminated by ',' location '/ext_users';
load data local inpath '/root/CodeProject/hive-advance/data.txt' into table ext_users;
select * from ext_users;
丢弃外部表时,Hive只会删除元数据,而不会删除HDFS目录上的数据。
3. 分区表
Hive把表组织成分区,这是一种根据分区列的值对表进行粗略划分的机制。使用分区,可以加快数据分片的查询速度。由于Hive使用的是读时模式,查询时无论是否带有附加的查询条件,Hive都需要对数据仓库中的数据文件进行全扫描,而对表进行分区则表示在数据时就会根据分区条件将对应的数据放置到不同的子文件夹中,此时如果利用分区条件作为查询条件使用,则进行全表扫描的数据文件数量将大大缩小,从而优化查询的效率。
创建分区表必须使用partitioned by (分区字段名,分区字段类型)
来标识分区字段。
create table p_users (user_id int, fname string, lname string) partitioned by (dt string, country string) row format delimited fields terminated by ',';
load data local inpath '/root/CodeProject/hive-advance/data.txt' into table p_users partition (dt='2016-8-1', country='GB');
load data local inpath '/root/CodeProject/hive-advance/data.txt' into table p_users partition (dt='2018-7-4', country='US');
hadoop fs -ls -R /user/hive/warehouse/p_users
查看某个表的分区:show partitions p_users;
select * from p_users where dt='2018-7-4' and country='US';
select * from p_users;
分区列在数据文件中没有对应的列,但也可以作为普通字段显示,但只有查询字段的where条件与分区字段信息一致时,才可以起到加快查询速度的作用。
参考
吴章勇 杨强著 大数据Hadoop3.X分布式处理实战