我有一个问题,需要在另一个RDD中搜索一个RDD的内容。
这个问题与Efficient string matching in Apache Spark不同,因为我正在寻找完全匹配的项目,并且不需要使用ML堆栈的开销。
我是火花的新手,我想知道这些方法中哪种更有效,或者是否还有其他方法。 我有一个类似以下示例的关键字文件(在生产中,它可能达到200行)
示例关键字文件
0.47uF 25V X7R 10% -TDK C2012X7R1E474K125AA
20pF-50V NPO/COG - AVX- 08055A200JAT2A
我还有另一个文件(用制表符分隔),需要从中查找匹配项(在生产中,我最多有80条 Million 行)
C2012X7R1E474K125AA Conn M12 Circular PIN 5 POS Screw ST Cable Mount 5 Terminal 1 Port
第一种方法
我定义了UDF
并在每一行中遍历关键字
keywords = sc.textFile("keys")
part_description = sc.textFile("part_description")
def build_regex(keywords):
res = '('
for key in keywords:
res += '(?<!\\\s)%s(?!\\\s)|' % re.escape(key)
res = res[0:len(res) - 1] + ')'
return r'%s' % res
def get_matching_string(line, regex):
matches = re.findall(regex, line, re.IGNORECASE)
matches = list(set(matches))
return list(set(matches)) if matches else None
def find_matching_regex(line):
result = list()
for keyGroup in keys:
matches = get_matching_string(line, keyGroup)
if matches:
result.append(str(keyGroup) + '~~' + str(matches) + '~~' + str(len(matches)))
if len(result) > 0:
return result
def split_row(list):
try:
return Row(list[0], list[1])
except:
return None
keys_rdd = keywords.map(lambda keywords: build_regex(keywords.replace(',', ' ').replace('-', ' ').split(' ')))
keys = keys_rdd.collect()
sc.broadcast(keys)
part_description = part_description.map(lambda item: item.split('\t'))
df = part_description.map(lambda list: split_row(list)).filter(lambda x: x).toDF(
["part_number", "description"])
find_regex = udf(lambda line: find_matching_regex(line), ArrayType(StringType()))
df = df.withColumn('matched', find_regex(df['part_number']))
df = df.filter(df.matched.isNotNull())
df.write.save(path=job_id, format='csv', mode='append', sep='\t')
第二种方法 我以为我可以做更多的并行处理(而不是像上面那样遍历所有键),所以我在键和线之间做了笛卡尔积,分解并分解了键,然后将每个键与part列进行了比较
df = part_description.cartesian(keywords)
df = df.map(lambda tuple: (tuple[0].split('\t'), tuple[1])).map(
lambda tuple: (tuple[0][0], tuple[0][1], tuple[1]))
df = df.toDF(['part_number', 'description', 'keywords'])
df = df.withColumn('single_keyword', explode(split(F.col("keywords"), "\s+"))).where('keywords != ""')
df = df.withColumn('matched_part_number', (df['part_number'] == df['single_keyword']))
df = df.filter(df['matched_part_number'] == F.lit(True))
df.write.save(path='part_number_search', format='csv', mode='append', sep='\t')
这些是正确的方法吗?我有什么办法可以更快地处理这些数据?
答案 0 :(得分:1)
这些都是有效的解决方案,我在不同的情况下都使用过。
通过使用广播方法传递的数据更少,向每个执行器仅发送200条额外的行,而不是将您的> 80m行文件的每一行复制200次,因此这可能最终为您带来更快的速度。
当查找中的记录数无法实现广播(远大于200行)时,我使用了笛卡尔方法。
在您的情况下,我会使用广播。