성능 차이 map () 대 withColumn ()
100 개 이상의 열이있는 테이블이 있습니다. 특정 열에서 큰 따옴표를 제거해야합니다. withColumn () 및 map ()을 사용하여 두 가지 방법을 찾았습니다.
withColumn () 사용
cols_to_fix = ["col1", ..., "col20"]
for col in cols_to_fix:
df = df.withColumn(col, regexp_replace(df[col], "\"", ""))
map () 사용
def remove_quotes(row: Row) -> Row:
row_as_dict = row.asDict()
cols_to_fix = ["col1", ..., "col20"]
for column in cols_to_fix:
if row_as_dict[column]:
row_as_dict[column] = re.sub("\"", "", str(row_as_dict[column]))
return Row(**row_as_dict)
df = df.rdd.map(remove_quotes).toDF(df.schema)
여기 내 질문이 있습니다. ~ 2,500 만 개의 레코드가있는 테이블에서 map ()을 사용하면 withColumn ()보다 약 4 배 더 오래 걸립니다. 동료 스택 오버플로 사용자가 성능 차이에 대한 이유를 설명 할 수 있다면 정말 감사하겠습니다. 그래야 나중에 유사한 함정을 피할 수 있습니다.
답변
첫째, 한 가지 조언 : DataFrame을 RDD로 변환하지 말고 df.map (여기에서 함수) 만 수행하면 많은 시간을 절약 할 수 있습니다. 다음 페이지https://dzone.com/articles/apache-spark-3-reasons-why-you-should-not-use-rdds 데이터 프레임에서 RDD 로의 변환에 사용되는 시간은 말할 것도없고 RDD가 DataFrame / Dataset보다 현저히 느리다는 것이 주요 결론입니다.
이제 DataFrame에서 RDD 로의 변환없이 map 및 withColumn에 대해 이야기 해 보겠습니다. 결론 우선 : 맵은 일반적으로 withColumn보다 5 배 느립니다. 그 이유는 withColumn이 관심있는 열에서 작동 할 수있는 반면 맵 작업에는 항상 역 직렬화 및 직렬화가 포함되기 때문입니다. 구체적으로 말하면, 맵 작업은 작업이 수행 될 여러 부분으로 행을 역 직렬화해야합니다.
여기에 예 : + -------- + ----------- + | language | users_count |와 같은 DataFrame이 있다고 가정합니다. + -------- + ----------- + | 자바 | 20000 | | 파이썬 | 100000 | | 스칼라 | 3000 | + -------- + ----------- + 그러면 users_count 열의 모든 값을 1 씩 증가시키고 싶습니다. 다음과 같이 할 수 있습니다.
df.map(row => {
val usersCount = row.getInt(1) + 1
(row.getString(0), usersCount)
}).toDF("language", "users_count_incremented_by_1")
위의 코드에서 먼저 두 번째 열의 값을 추출하기 위해 모든 행을 역 직렬화해야합니다. 그런 다음 수정 된 값을 출력하고이를 DataFrame으로 저장합니다 (이 단계에서는 (a, b)를 Row (a, b) DataFrame은 행의 DataSet 일 뿐이므로). 자세한 설명은 다음 우수 기사를 확인하십시오.https://medium.com/@fqaiser94/udfs-vs-map-vs-custom-spark-native-functions-91ab2c154b44
map은 열 자체에서 작동 할 수 없지만 열의 값에 대해 작동해야합니다. 값을 가져 오려면 역 직렬화가 필요하며 데이터 프레임으로 저장하려면 직렬화가 필요합니다.
그러나 map은 여전히 많이 사용됩니다. map 메소드의 도움으로 사람들은 매우 정교한 작업을 구현할 수 있으며 withColumn 만 사용하면 내장 작업을 수행 할 수 있습니다.
요약하자면 map은 느리지 만 더 유연합니다. withColumn은 기능이 제한되어 있지만 확실히 가장 효율적입니다.