2021SC@SDUSC
Data目录文件列表如下
文件很多,我们先了解Pig的数据结构,再进行分析,其中一个很重要的概念是数据模型
相关资料链接:【Pig源码分析】谈谈Pig的数据模型 -数据库-火龙果软件工程
数据模型Schema
Schema为数据所遵从的类型格式,包括两个部分:
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<Tuple>。在方法TupleFactory.getInstance()中,默认情况下返回的是BinSedesTupleFactory对象,同时支持加载用户重写的TupleFactory类(pig.data.tuple.factory.name指定类名、 pig.data.tuple.factory.jar指定类所在的jar)。BinSedesTupleFactory继承于TupleFactory:
在BinSedesTupleFactory的newTuple方法中,返回的是BinSedesTuple对象。BinSedesTuple类继承于DefaultTuple类,在DefaultTuple类中有List<Object> mFields字段,这便是存储Tuple数据的地方了,mFields所持有类型为ArrayList<Object>();。类图关系:
笔记:这篇博客已经将Tuple整体脉络整理地非常清楚了,我们继续看一些细节
TupleFactory.java开头有以下注释
这是一个构造元组的工厂。这个类是抽象的,因此用户可以重写元组工厂,如果他们想提供自己的
返回它们对元组的实现。如果属性pig.data.tuple.factory.name设置为类名 pig.data.tuple.factory.jar被设置为一个指向jar的URL包含上面命名的类,然后{@link #getInstance()}将创建一个指定类的实例,使用指定的jar。否则,它将创建一个{@link DefaultTupleFactory}的实例
原文
/** * A factory to construct tuples. This class is abstract so that users can * override the tuple factory if they desire to provide their own that * returns their implementation of a tuple. If the property * pig.data.tuple.factory.name is set to a class name and * pig.data.tuple.factory.jar is set to a URL pointing to a jar that * contains the above named class, then {@link #getInstance()} will create a * an instance of the named class using the indicated jar. Otherwise, it * will create an instance of {@link DefaultTupleFactory}. */
TupleFactory实现的函数:
获取对单例工厂的引用。
@return用于构造元组的TupleFactory
/** * Get a reference to the singleton factory. * @return The TupleFactory to use to construct tuples. */ public static TupleFactory getInstance()
创建一个空元组。这个(函数)应该尽量少用
,使用newTuple(int)代替。
@return空的新元组
/** * Create an empty tuple. This should be used as infrequently as * possible, use newTuple(int) instead. * @return Empty new tuple. */ public abstract Tuple newTuple();
创建一个具有size字段的元组。只要可能,这是首选
*在null构造函数上,因为构造函数可以预分配
*存放字段的容器大小。一旦这个被调用,它
*是合法的调用Tuple。Set (x, object),其中x <大小。
* @param size元组字段个数。
* @return带有size字段的元组
/** * Create a tuple with size fields. Whenever possible this is preferred * over the null constructor, as the constructor can preallocate the * size of the container holding the fields. Once this is called, it * is legal to call Tuple.set(x, object), where x < size. * @param size Number of fields in the tuple. * @return Tuple with size fields */ public abstract Tuple newTuple(int size);
从提供的对象列表创建一个元组。底层列表 *将被复制。 * @param c用于作为元组字段的对象列表。 * @return一个以列表对象作为字段的元组 /** * Create a tuple from the provided list of objects. The underlying list * will be copied. * @param c List of objects to use as the fields of the tuple. * @return A tuple with the list objects as its fields */ public abstract Tuple newTuple(List c);
从提供的对象列表创建一个元组,保持所提供的 *列表。新的元组将接管所提供列表的所有权。 * @param list将成为元组字段的对象列表。 * @return一个以列表对象作为字段的元组 /** * Create a tuple from a provided list of objects, keeping the provided * list. The new tuple will take over ownership of the provided list. * @param list List of objects that will become the fields of the tuple. * @return A tuple with the list objects as its fields */ public abstract Tuple newTupleNoCopy(List list); 用单个元素创建一个元组。这很有用,因为 事实上,包(目前)只接受元组,我们经常结束 *将单个元素放入元组中,以便将其放入包中。 * @param datum放入元组的数据。 * @return一个只有一个字段的元组 /** * Create a tuple with a single element. This is useful because of * the fact that bags (currently) only take tuples, we often end up * sticking a single element in a tuple in order to put it in a bag. * @param datum Datum to put in the tuple. * @return A tuple with one field */ public abstract Tuple newTuple(Object datum); 返回表示实现的元组的实际类 *工厂将返回。这是需要的,因为Hadoop需要 *以了解我们将用于输入和输出的确切类。 * @return实现元组的类 /** * Return the actual class representing a tuple that the implementing * factory will be returning. This is needed because Hadoop needs * to know the exact class we will be using for input and output. * @return Class that implements tuple. */ public abstract Class<? extends Tuple> tupleClass(); protected TupleFactory() { } 仅供测试之用。这个函数不应该是 *被任何人调用,但单元测试 /** * Provided for testing purposes only. This function should never be * called by anybody but the unit tests. */ public static void resetSelf() { gSelf = null; } 返回实现元组原始比较器的实际类 工厂将会返回。重写此选项以允许Hadoop *加快元组排序。实际返回的类应该知道 *元组的序列化细节。默认实现 * (PigTupleDefaultRawComparator)将在比较之前序列化数据 * @return实现元组原始比较器的类 /** * Return the actual class implementing the raw comparator for tuples * that the factory will be returning. Ovverride this to allow Hadoop to * speed up tuple sorting. The actual returned class should know the * serialization details for the tuple. The default implementation * (PigTupleDefaultRawComparator) will serialize the data before comparison * @return Class that implements tuple raw comparator. */ public Class<? extends TupleRawComparator> tupleRawComparatorClass() { return PigTupleDefaultRawComparator.class; } 此方法用于检查该工厂是否创建了元组 *将是一个固定的大小时,他们被创建。在实践中,这意味着 *是否支持append。 * @return该元组是否固定 /** * This method is used to inspect whether the Tuples created by this factory * will be of a fixed size when they are created. In practical terms, this means * whether they support append or not. * @return where the Tuple is fixed or not */ public abstract boolean isFixedSize();
总结:TupleFactory是个抽象类,除了getInstance外其他大多没给出实现,等待继承它的类来实现,至于TupleMaker更加简单粗暴,以下为其代码
显然,这样的设计是一种面向对象的设计,是为了面向对象而服务的
那么,本次的代码分析就到这里