近期小结

这周没安排好时间,又没能好好写一篇文章,真心惭愧,只能希望每次都惭愧一下,总有一天能良心发现,好好做人……

就随便写点小结吧,总结一下这两周干得各种蠢事,和一些小tip吧。

首先是关于hadoop streaming的。

1、千万不要把注释加在几个参数项之间,结果你懂的。(这当然要2到一定程度才会这样做)
2、有一个很实用的二次排序功能。使用:
-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner \
-jobconf stream.num.map.output.key.fields=2 \
-jobconf num.key.fields.for.partition=1 \
这些选项,可以实现reduce的二次排序,具体的说就是设置的num.key.fields.for.partition将表示分桶的key,相当于主键。比如这里是1,就表示从第一个分隔符往前的内容都作为key来分到不同的reduce里,这里默认分隔符为’/t’,当然也可以在配置里改,不过不是很实用,因为用别的分隔符最后输出的时候hadoop还是会把分隔符替换为’/t’(我看的官方文档的例子好像没体现这一点,但是我自己实际操作的时候发现是会被替换掉的……),而map的输出其实我们是可控的,所以还是养成良好习惯就用默认的比较靠谱,如果需要用别的,可以在reduce阶段接收输入时再换回来。stream.num.map.output.key.fields按字面看这个值就是指以第几个分隔符之前的值作为map输出的key,在这里是2,那就是从第二个’/t’之前都作为map输出的key,而map的输出是会按key排序的,这就意味着在主键相同的情况下,不同的value值就会按照第一个分隔符和第二分隔符之间的内容(相当于辅键)进行排序,这样就实现了二次排序。这个功能在很多场合还是很有用的,不仅省去了在reduce中做二次排序的工作,预排序也可以节省很多reduce的资源。
3、在编写reduce程序时一定要时刻牢记处理的数据是已经预排序过的,这样可以很容易使用一些节省内存和计算资源的算法。避免137错误。
4、在配置中要注意hadoop streaming的配置项中使用转义符是无效的(原因可能和echo中直接使用转义符是无效的一样),所以遇到’\t’的时候还是直接敲tab键吧,如果在命令行状态下,记得先ctrl+v,再敲tab键……(我在这个坑里爬了好久T_T,开始的时候一直不明白,为什么切分的分隔符不是用预想的分隔符……现在想来真是不可思议,弱爆了)。

补充一条刚回忆起来的:用map_input_file这个环境变量可以获取到map输入文件的名字,当map有不同格式的输入时,这个变量还是很有用的。

其次是关于sqlite的,sqlite的效率还是不错的,我开始的时候有点冤枉它了,不过要最快还是要直接调c的api,并且使用事务批量提交(如果数据量很大的话),另外在一次传入多条语句的时候,一定要记得在语句中间加换行,不然如果传入的语句较多,sqlite会慢得让你怀疑上帝(我真心错了,一开始怀疑的是sqlite的性能不行=_+)

第三,少在脚本里面用grep和管道,特别是本来就有逐行处理的逻辑的时候,能用截断解析就截断解析,能用awk就用awk(据说用awk比直接cat速度还快)。发现这些还要拜上面那个sqlite的坑所赐,我把一个脚本前前后后的速度都测了一遍,优化了一下,还是快了不少了(虽然后来发现改掉sqlite的那个换行问题才是让速度飞起来的关键=_=)

第四,送给那些像我一样对gdb心怀敬畏和恐惧的人,其实gdb调多线程程序也并不是非常麻烦,当然如果总在多个线程间跳来跳去可能是挺让人头大的,但是如果只是想调一个被多线程调用的模块,且逻辑完整简单的话,还是很方便的,直接在那个模块代码那里打上断点,然后一个run就能到你想要去的地方~当然在编写代码阶段,养成良好的习惯,把日志打全,从根本上避免调试才是王者之道,不过有的时候维护别人的代码或者编译时间太长的时候,调试还是有它存在的价值的。

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *