개발/Spark

[Spark] Parquet 파일을 읽는 동안 Dataframe의 메타데이터 변경 에러

wonpick 2023. 7. 16. 23:58

이 포스팅에서는 Parquet 파일을 읽는 동안 Dataframe의 메타데이터가 수정 되었을 경우 "REFRESH TABLE tableName"에러가 뜨는 문제를 어떻게 해결할 수 있는지 알아보겠습니다.

 

기존의 모든 배치에서는 동일 파티션에 대해 .mode("overwrite")를 사용하기 때문에,  프로세스가 실행되는 동안 수정/삭제된 파일을 읽으려고 시도하게 되면 메타데이터가 변경되었다는 "REFRESH TABLE tableName" 에러가 발생합니다. 이로 인해 해당 파티션이 저장 중 상태인 temporary 에서는 테이블을 사용할 수 없게 됩니다.

 

따라서 아래와 같이 메타데이터를 메모리 위에 올려주거나 다른 dump와 같은 경로에 저장을 하는 방법 등으로 해결할 수 있습니다.

저는 그 중 DataFrame.createOrReplaceTempView() 메서드를 통해 DataFrame 을 View 로 등록해 SQL 내에서 테이블처럼 사용하여 CACHE TABLE 구문을 이용해 캐싱하는 방식으로 문제를 해결하였습니다.

 

df.createOrReplaceTempView("table")

df_cache = spark.sql("""
                    CACHE TABLE testCache AS(
                        SELECT * 
                        FROM testData 
                        WHERE ~
                    )
                    """)

CreateOrReplaceTempView 란? 

  • 새로 테이블을 생성하는 것이 아닌, 임시뷰를 만드는 것인데 Spark는 Lazy evaluation이기 때문에 호출할때마다 연산이 이루어집니다. 따라서 메모리에 올리고 싶다면 캐싱을 해야합니다.
  • 일시적인 뷰는 Spark 세션이 유지되는 동안에만 존재하므로, 새로운 Spark 세션을 시작하면 뷰가 사라집니다. 
  • 세션을 종료시키지 않을거라면 , dropTempView로 뷰를 드랍해주고 캐싱까지 했다면 unpersist를 통해 할당 된 메모리를 해제 시켜줘야 합니다.

 

Global Temporary View 란? 

temp view를 GlobalTempViewGlobal 로 만들면 뷰를 등록한 Spark 세션이 종료되더라도, 다른 Spark 세션에서 접근하여 사용할 수 있습니다. 이는 여러 사용자가 하나의 뷰를 공유하거나, 다른 세션에서 임시 결과를 재사용해야하는 경우 유용합니다.

# Global Temporary View 생성
df.createGlobalTempView("temp_df")
# 다른 Spark 세션에서 접근 가능한 Global Temporary View
global_temp_df = spark.table("global_temp.temp_df")

하지만 메타스토어 부하 및 워커 노드의 메모리 부족 문제가 발생할 수 있기 때문에 Global Temporary View 사용은 지양하는 것이 좋습니다.


 

1.  Practical Spark – SQL & Table (8)