Hive的一些问题

阅读更多

偏激了一点.

总体来说Hive的思想是不错的, 思路是清晰的, 但代码也是啰嗦的, 简单的功能非得涉及到3,4个类,有时候十多个类。

 

1. 实现代码过量使用自己造的术语以及由它们引申的术语,导致代码理解起来非常困难, 例如SerDe(DynamicSerDe, LazySimpleSerDe), 如果说SerDe从字面Deserializer+Serializer还比较好理解的话. 那么RowResolver, ObjectInspector就无从知道了,  更严重的是这些关键类几乎没有文档说明, 而且这些类都有密切的关系. 

还有一例:  *Desc,  *Work, *Task. 静下心来, 还是能理解的, 为了序列化成必须有像*Desc这样的东西, 但这些东西一多, 就会看到代码充斥着这些类的实例, 而且非常多代码去维护它们之间的关系. 

 

2. thrift, thrift这东西本来就不是开源界所广泛接受的东西,当然facebook使用自己的东西也无可厚非. 但如果要把HiveServer做成多用户的Server, thrift行不行那还得考量. 我尝试过, 这种RPC做各进程交换数据, 相互调用还是非常方便的, 但是做Server不是很方便.

 

3. SessionState. 使用ThreadLocal将各会话的数据进行线程封闭, 造成了太多地方使用SessionState.get(). 像全局变量一样, 引入隐晦的类间耦合.

 

4.  细节. reduceSinkDesc里有两个tableDesc成员变量,乍一看让人不解.  map输出操作的时候, 要table描述干嘛? 仔细一看, 其实只要用到它的序列化及反序列化功能.  在PlanUtils. getBinarySortableTableDesc()方法内大张旗鼓地向tableDesc灌入DynamicSerDe, SequenceFileInputFormat, SequenceFileOutputFormat...实际上ReduceSinkOperator只需要那个SerDe去解析key/value.

这个tableDesc很滑稽. groupby_key+ distinct_key形成了ExecMapper要输出的key, reducekey由SemanticAnalyzer. genGroupByPlanReduceSinkOperator()组合, 然后调用PlanUtils.getReduceSinkDesc()方法按照keyCols建立一个tableDesc, 它的ddl样子如下

struct binary_sortable_table

{

  类型名  reducekey0,

  类型名  reducekey1,

  ...

}

这个tableDesc开始是放在reduceSinkDesc中的, 用来给mapper序列化key, 但是reducer得到key要反序列化它啊, 否则怎么知道这个key的内容?  所以reducer也要得到这个tableDesc. 怎么得到呢? 在mapredWork里面有个tableDesc keyDesc, 在hdfs上建立plan.[0-9]+文件,reducer可以从这里得到。 但这个tableDesc是怎么传给mapredWork的呢? 本来它是在reduceSinkDesc里面啊.  仔细一找, SemanticAnalyzer.analyzeInteral的最后一步genMapRedTasks(qb) ->setKeyDescTaskTree(rootTask) ->GenMapRedUtils.setKeyAndValueDesc(work, op) -> ReduceSinkOperator rs = (ReduceSinkOperator)topOp; plan.setKeyDesc(rs.getConf().getKeySerializeInfo());

 

曲曲折折, 终于把这个tableDesc从reduceSinkDesc赋给了mapredWork, 终于reducer可以得到它了, 上帝都感动得哭了!

 

 

5. 细节.   GenericUDF不错, 但initialize必须得返回非null实例, 否则hive会抛出NullPointerException而crash.  造成一下假设: 扩展人员知道这个情况, 但很多时候大家是不知道的. 

GenericUDFUtils.ReturnObjectInspectorResolver. update(oi), 如果传进去的oi一直为null, 那它由get()返回的ObjectInspector必定为null, 从而initialize()返回null, 作者本人都不知道会有这种情况.

看GenericUDFHash的代码, initialize返回一个PrimitiveObjectInspectorFactory.writableIntObjectInspector作为trick,  骗骗其它的代码.  其实在evaluate的时候根本没用. 好的代码不应该给别人造成side impression(not effect here).

 

6. 看过代码,你会发现解析thrift文法(如DynamicSerDe类)用的是JavaCC做的lexer&parser, 而Hive的sql解析则用的是antlr生成的lexer&parser.也就是说,要掌握hive这个项目,你至少要会两种CC.

 

7. 细节. reduceSinkDesc有两个成员keyCols和partitionCols, 分别用来做为map输出的key和partition, 其实在group by的时候.  partitionCols是reduceSinkDesc的一部分. 没有必要copy成两份, 这个partitionCols没有带来更灵活的partition功能.

 

 

 

未完待续

 

 

你可能感兴趣的:(SQL,Server,Facebook,多线程,SQL)