BigQuery DataFrames 성능 최적화

BigQuery DataFrames를 사용하면 pandas 호환 API를 사용하여 BigQuery에서 데이터를 분석하고 변환할 수 있습니다. 데이터 처리를 더 빠르고 비용 효율적으로 만들기 위해 성능을 개선하는 여러 기법을 사용할 수 있습니다.

이 문서에서는 성능을 최적화하는 다음 방법을 설명합니다.

부분 순서 지정 모드 사용

BigQuery DataFrames에는 윈도우 함수 및 조인과 같은 작업에 특정 행 순서를 적용하는 순서 지정 모드 기능이 있습니다. ordering_mode 속성을 strict (엄격한 순서 지정 모드라고 하며 기본값임) 또는 partial (부분 순서 지정 모드라고 함)로 설정하여 순서 지정 모드를 지정할 수 있습니다. partial 설정을 사용하면 쿼리를 더 효율적으로 만들 수 있습니다.

부분 순서 지정 모드는 엄격한 순서 지정 모드와 다릅니다. 엄격한 순서 지정 모드는 모든 행을 특정 순서로 정렬합니다. 이 총 순서를 통해 BigQuery DataFrames가 Pandas와 더 잘 작동하므로 DataFrame.iloc 속성을 사용하여 순서별로 행에 액세스할 수 있습니다. 그러나 총 순서와 기본 순차 색인으로 인해 열이나 행의 필터가 스캔되는 데이터의 양을 줄일 수 없습니다. 이러한 필터를 read_gbqread_gbq_table 함수의 매개변수로 적용하지 않으면 이러한 방지가 발생합니다. DataFrame의 모든 행을 정렬하기 위해 BigQuery DataFrames는 모든 행의 해시를 만듭니다. 이 작업으로 인해 행 및 열 필터를 무시하는 전체 데이터 스캔이 발생할 수 있습니다.

부분 순서 지정 모드는 BigQuery DataFrames가 모든 행에 대한 총 순서를 생성하지 못하도록 하고 DataFrame.iloc 속성과 같이 총 순서가 필요한 기능을 사용 중지합니다. 부분 순서 지정 모드는 DefaultIndexKind 클래스를 순차 색인이 아닌 null 색인으로 설정합니다.

부분 순서 지정 모드를 사용하여 DataFrame 객체를 필터링하면 BigQuery DataFrames에서 순차 색인에 누락된 행을 계산하지 않습니다. 부분 순서 지정 모드는 색인을 기반으로 데이터를 자동으로 결합하지도 않습니다. 이러한 접근 방식을 사용하면 쿼리의 효율성을 높일 수 있습니다. 하지만 기본 엄격한 순서 지정 모드를 사용하든 부분 순서 지정 모드를 사용하든 BigQuery DataFrames API는 친숙한 Pandas API처럼 작동합니다.

부분 순서 지정 모드와 엄격한 순서 지정 모드 모두에서 사용한 BigQuery 리소스의 비용을 지불합니다. 그러나 대규모 클러스터링된 테이블 및 파티션을 나눈 테이블을 사용할 때 부분 순서 지정 모드를 사용하면 비용을 줄일 수 있습니다. 클러스터 및 파티션 열의 행 필터는 처리되는 데이터 양을 줄여주므로 비용이 절감됩니다.

부분 순서 지정 모드 사용 설정

부분 순서 지정을 사용하려면 다음 코드 샘플과 같이 BigQuery DataFrames로 다른 작업을 수행하기 전에 ordering_modepartial로 설정하세요.

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

부분 순서 지정 모드에는 순차 색인이 없으므로 관련 없는 BigQuery DataFrames 객체의 암시적 조인이 방지됩니다. 대신 DataFrame.merge 메서드를 명시적으로 호출하여 서로 다른 테이블 표현식에서 파생된 두 개의 BigQuery DataFrame 객체를 조인해야 합니다.

Series.unique()Series.drop_duplicates() 기능은 부분 순서 지정 모드와 호환되지 않습니다. 대신 다음 예와 같이 groupby 메서드를 사용하여 고유한 값을 찾습니다.

# Avoid order dependency by using groupby instead of drop_duplicates.
unique_col = df.groupby(["column"], as_index=False).size().drop(columns="size")

부분 순서 지정 모드를 사용하면 DataFrame.head(n)Series.head(n) 함수의 출력이 실행할 때마다 동일하지 않을 수 있습니다. 데이터의 작은 무작위 샘플을 다운로드하려면 DataFrame.peek() 또는 Series.peek() 메서드를 사용하세요.

ordering_mode = "partial" 속성을 사용하는 자세한 튜토리얼은 BigQuery DataFrames를 사용하여 PyPI의 패키지 다운로드 분석을 참고하세요.

문제 해결

부분 순서 지정 모드의 BigQuery DataFrames에는 순서 지정 또는 색인이 없는 경우가 있으므로 pandas와 호환되는 일부 메서드를 사용할 때 다음 문제가 발생할 수 있습니다.

순서 필요 오류

DataFrame.head()DataFrame.iloc 함수와 같은 일부 기능에는 순서 지정이 필요합니다. 순서 지정이 필요한 기능 목록은 지원되는 Pandas API순서 지정 필요 열을 참고하세요.

객체에 순서가 없으면 다음과 같은 OrderRequiredError 메시지와 함께 작업이 실패합니다. OrderRequiredError: Op iloc requires an ordering. Use .sort_values or .sort_index to provide an ordering.

오류 메시지에 설명된 대로 DataFrame.sort_values() 메서드를 사용하여 순서를 지정하면 하나 이상의 열을 기준으로 정렬할 수 있습니다. DataFrame.groupby()과 같은 다른 메서드는 키별로 그룹을 기반으로 총 순서를 암시적으로 제공합니다.

순서 지정이 모든 행에 대해 완전히 안정적인 총 순서가 아닌 경우 후속 작업에서 다음과 같은 AmbiguousWindowWarning 메시지를 표시할 수 있습니다. AmbiguousWindowWarning: Window ordering may be ambiguous, this can cause unstable results.

작업에서 항상 동일하지 않은 결과를 처리할 수 있거나 순서가 총 순서인지 수동으로 확인할 수 있는 경우 다음과 같이 AmbiguousWindowWarning 메시지를 필터링할 수 있습니다.

import warnings

import bigframes.exceptions

warnings.simplefilter(
    "ignore", category=bigframes.exceptions.AmbiguousWindowWarning
)

null 색인 오류

DataFrame.unstack()Series.interpolate() 속성과 같은 일부 기능에는 색인이 필요합니다. 색인이 필요한 기능 목록은 지원되는 Pandas API색인 필요 열을 참고하세요.

부분 순서 지정 모드와 함께 색인이 필요한 작업을 사용하면 작업에서 다음과 같은 NullIndexError 메시지를 발생시킵니다. NullIndexError: DataFrame cannot perform interpolate as it has no index. Set an index using set_index.

오류 메시지에 설명된 대로 DataFrame.set_index() 메서드를 사용하여 색인을 제공하면 하나 이상의 열을 기준으로 정렬할 수 있습니다. DataFrame.groupby()과 같은 다른 메서드는 as_index=False 파라미터가 설정되지 않는 한 키별로 그룹에 대한 색인을 암시적으로 제공합니다.

비용이 많이 드는 작업 후 결과 캐시

BigQuery DataFrames는 작업을 로컬에 저장하고 특정 조건이 충족될 때까지 쿼리 실행을 지연합니다. 이로 인해 서로 다른 쿼리에서 동일한 작업이 여러 번 실행될 수 있습니다.

비용이 많이 드는 작업을 반복하지 않으려면 다음 예와 같이 cache() 메서드로 중간 결과를 저장하세요.

# Assume you have 3 large dataframes "users", "group" and "transactions"

# Expensive join operations
final_df = users.join(groups).join(transactions)
final_df.cache()
# Subsequent derived results will reuse the cached join
print(final_df.peek())
print(len(final_df[final_df["completed"]]))
print(final_df.groupby("group_id")["amount"].mean().peek(30))

이 메서드는 결과를 저장하기 위한 임시 BigQuery 테이블을 만듭니다. BigQuery의 이 임시 테이블 스토리지에 요금이 청구됩니다.

peek() 메서드로 데이터 미리보기

BigQuery DataFrames는 데이터를 미리 볼 수 있는 두 가지 API 메서드를 제공합니다.

  • peek(n)n개의 데이터 행을 반환합니다. 여기서 n은 행 수입니다.
  • head(n)는 컨텍스트에 따라 데이터의 처음 n개 행을 반환합니다. 여기서 n은 행 수입니다.

데이터 순서가 중요한 경우에만 head() 메서드를 사용하세요(예: 열에서 가장 큰 값 5개를 원하는 경우). 다른 경우에는 다음 코드 샘플에 표시된 대로 peek() 메서드를 사용하여 데이터를 더 효율적으로 가져옵니다.

import bigframes.pandas as bpd

# Read the "Penguins" table into a dataframe
df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins")

# Preview 3 random rows
df.peek(3)

부분 순서 지정 모드를 사용하는 동안 peek() 메서드를 사용하여 소규모의 무작위 데이터 샘플을 다운로드할 수도 있습니다.

repr() 데이터 검색 지연

노트북 또는 IDE 디버거를 사용하여 BigQuery DataFrames에서 repr() 메서드를 호출할 수 있습니다. 이 호출은 실제 데이터를 가져오는 head() 호출을 트리거합니다. 이러한 검색으로 인해 반복적인 코딩 및 디버깅 프로세스가 느려지고 비용이 발생할 수도 있습니다.

repr() 메서드가 데이터를 가져오지 못하도록 하려면 다음 예와 같이 repr_mode 속성을 "deferred"로 설정합니다.

import bigframes.pandas as bpd

bpd.options.display.repr_mode = "deferred"

지연 모드에서는 명시적 peek()head() 호출을 통해서만 데이터를 미리 볼 수 있습니다.

다음 단계