所以要澄清一些事情:
Mahout 的 XMLInputFormat 将处理 XML 文件并提取两个配置的开始/结束标记之间的 XML。因此,如果您的 XML 如下所示:
<main>
<person>
<name>Bob</name>
<dob>1970/01/01</dob>
</person>
</main>
并且您已将开始/结束标签配置为<person>
and </person>
,那么您的映射器将通过以下<LongWritable, Text>
对传递给它的 map 方法:
LongWritable: 10
Text: "<person>\n <name>Bob</name>\n <dob>1970/01/01</dob>\n </person>"
然后,您在映射器中如何处理这些数据取决于您。
关于拆分、XmlInputFormat
扩展TextInputFormat
,因此如果您的输入文件是可拆分的(即未压缩或使用可拆分的编解码器(如 snappy)压缩),则该文件将由一个或多个映射器处理,如下所示:
- 如果输入文件大小(比如 48 MB)小于 HDFS 中的单个块(比如 64MB),并且您没有配置最小/最大拆分大小属性,那么您将获得一个单独的映射器来处理文件
- 与上面一样,但是您将最大拆分大小配置为 10MB (
mapred.max.split.size=10485760
),那么您将获得 5 个地图任务来处理文件
- 如果文件大于块大小,那么您将获得每个块的映射任务,或者如果配置了最大拆分大小,则文件的每个部分按该拆分大小划分的映射
当文件被分割成这些块或分割大小的块时,XmlInputFormat 将寻找块/分割边界的字节地址/偏移量,然后向前扫描,直到找到配置的 XML 开始标记或到达块的字节地址/分割边界。如果找到开始标签,它将使用数据,直到找到结束标签(或文件结尾)。如果它找到结束标记,一条记录将传递给您的映射器,否则您的映射器将不会收到任何输入。需要强调的是,当试图找到结束标签时,地图可能会扫描超过块/拆分的末尾,但只有在找到开始标签时才会这样做,否则扫描会在块/拆分的末尾停止。
所以(最终)回答你的问题,如果你没有配置一个映射器(并且正在使用默认值或识别映射器,因为它也是已知的),那么是的,XML块有多大(MB,GB , TB 的!)它将被发送到减速器。
我希望这是有道理的。
编辑
要跟进您的评论:
- 是的,每个映射器都将尝试处理文件的拆分(字节范围)
- 是的,无论您设置的最大拆分大小如何,您的映射器都将接收代表开始/结束标签之间(包括)之间数据的记录。person 元素无论其大小如何都不会被拆分(显然,如果在 start 和 end 元素之间存在 GB 的数据,您很可能会在尝试将其缓冲到 Text 对象中时耗尽内存)
- Continuing from the above, your data will never be split up between the start and end element, a person element will be sent in its entirity to a mapper, so you should always be ok using something like a SAX parser to further process it without fear that you're only seeing a portion of the person element.