2021SC@SDUSC
Data目录文件列表如下
文件很多,我们先了解Pig的数据结构,再进行分析,其中一个很重要的概念是数据模型
相关资料链接:【Pig源码分析】谈谈Pig的数据模型 -数据库-火龙果软件工程
数据模型SchemaSchema为数据所遵从的类型格式,包括两个部分:
field的 名称 类型
field表示数据块(A field is a piece of data)可理解为数据字段
Schema与Pig Latin的关系Pig Latin表达式操作的是relation,FILTER、FOREACH、GROUP、SPLIT等关系操作符所操作的relation就是bag,bag为tuple的集合,tuple为有序的field列表集合
因此,Schema是Pig Latin表达式操作的一个单元
用户常用as语句来自定义schema,或是load函数导入schema,比如:
若不指定field的类型,则其默认为bytearray。对未知schema进行操作时,有:
若join/cogroup/cross多关系操作遇到未知schema,则会将其视为null schema,导致返回结果的schema也为null;
若flatten一个empty inner schema的bag(即:bag{})时,则返回结果的schema为null;
若union时二者relation的schema不一致,则返回结果的schema为null;
若field的schema为null,会将该字段视为bytearray。
为了保证pig脚本运行的有效性,在写UDF时要在outputSchema方法中指定返回结果的schema。
注释:UDF为用户自定义函数(Userdefined function)
数据类型Pig的基本数据类型与对应的Java类:
复杂数据类型及其对应的Java类:
笔记:这里可以进一步理解Schama,如'hello'、18就是数据块field;有序field的集合是tuple,如(18,1),bag为tuple的集合,如{('hello'),(18,1)},某些操作符所操作的relation就是bag
Tuple源码分析在Data目录下搜索含有Tuple的文件名:
我们来参照上文提到文章里的内容:
在KEYSET源码中,创建Tuple对象采用工厂+单例设计模式:
private static final TupleFactory TUPLE_FACTORY = TupleFactory.getInstance(); Tuple t = TUPLE_FACTORY.newTuple(s); |
笔记:keyset.java位于目录,代码如下
其中,map为java自带的类,用法参照以下博客,我们只需要知道它是用于遍历的就行了
java笔记--Map的用法_Linias的博客-CSDN博客_java map
可以看见新建bag的代码为 new NonSpillableDataBag(m.szie()),新建tuple的代码为前面那两端代码
继续参考前面的博客:
事实上,TupleFactory是个抽象类,实现接口TupleMaker
在BinSedesTupleFactory的newTuple方法中,返回的是BinSedesTuple对象。BinSedesTuple类继承于DefaultTuple类,在DefaultTuple类中有List
笔记:这篇博客已经将Tuple整体脉络整理地非常清楚了,我们继续看一些细节
TupleFactory.java开头有以下注释
这是一个构造元组的工厂。这个类是抽象的,因此用户可以重写元组工厂,如果他们想提供自己的
返回它们对元组的实现。如果属性pig.data.tuple.factory.name设置为类名 pig.data.tuple.factory.jar被设置为一个指向jar的URL包含上面命名的类,然后{@link #getInstance()}将创建一个指定类的实例,使用指定的jar。否则,它将创建一个{@link DefaultTupleFactory}的实例
原文
TupleFactory实现的函数:
获取对单例工厂的引用。
@return用于构造元组的TupleFactory
public static TupleFactory getInstance()
创建一个空元组。这个(函数)应该尽量少用
,使用newTuple(int)代替。
@return空的新元组
public abstract Tuple newTuple();
创建一个具有size字段的元组。只要可能,这是首选
*在null构造函数上,因为构造函数可以预分配
*存放字段的容器大小。一旦这个被调用,它
*是合法的调用Tuple。Set (x, object),其中x <大小。
* @param size元组字段个数。
* @return带有size字段的元组
public abstract Tuple newTuple(int size);
从提供的对象列表创建一个元组。底层列表 *将被复制。 * @param c用于作为元组字段的对象列表。 * @return一个以列表对象作为字段的元组 public abstract Tuple newTuple(List c);
从提供的对象列表创建一个元组,保持所提供的
*列表。新的元组将接管所提供列表的所有权。
* @param list将成为元组字段的对象列表。
* @return一个以列表对象作为字段的元组
public abstract Tuple newTupleNoCopy(List list);
用单个元素创建一个元组。这很有用,因为
事实上,包(目前)只接受元组,我们经常结束
*将单个元素放入元组中,以便将其放入包中。
* @param datum放入元组的数据。
* @return一个只有一个字段的元组
public abstract Tuple newTuple(Object datum);
返回表示实现的元组的实际类
*工厂将返回。这是需要的,因为Hadoop需要
*以了解我们将用于输入和输出的确切类。
* @return实现元组的类
public abstract Class extends Tuple> tupleClass();
protected TupleFactory() {
}
仅供测试之用。这个函数不应该是
*被任何人调用,但单元测试
public static void resetSelf() {
gSelf = null;
}
返回实现元组原始比较器的实际类
工厂将会返回。重写此选项以允许Hadoop
*加快元组排序。实际返回的类应该知道
*元组的序列化细节。默认实现
* (PigTupleDefaultRawComparator)将在比较之前序列化数据
* @return实现元组原始比较器的类
public Class extends TupleRawComparator> tupleRawComparatorClass() {
return PigTupleDefaultRawComparator.class;
}
此方法用于检查该工厂是否创建了元组
*将是一个固定的大小时,他们被创建。在实践中,这意味着
*是否支持append。
* @return该元组是否固定
public abstract boolean isFixedSize();
总结:TupleFactory是个抽象类,除了getInstance外其他大多没给出实现,等待继承它的类来实现,至于TupleMaker更加简单粗暴,以下为其代码
显然,这样的设计是一种面向对象的设计,是为了面向对象而服务的
那么,本次的代码分析就到这里



