SQL 소개
SQL 소개
Polars는 SQL과의 상호작용을 지원하지만, 더 읽기 쉽고 표현력 있는 코드를 만들려면 표현식 문법에 익숙해지는 걸 권장해요. DataFrame 인터페이스가 주력이기 때문에 신규 기능도 보통 표현식 API에 먼저 추가됩니다. 다만 이미 기존 SQL 코드베이스가 있거나 SQL 사용이 더 편하다면, Polars도 이를 지원해 줍니다.
출처: 공식문서
실행 방식
별도의 SQL 엔진은 존재하지 않아요. Polars는 SQL 쿼리를 표현식으로 번역한 뒤 자체 엔진으로 실행합니다. 이 방식 덕분에 네이티브 DataFrame 라이브러리로서의 성능과 확장성 장점을 유지하면서도, 사용자에게는 SQL로 작업할 수 있는 능력을 제공할 수 있어요.
컨텍스트
Polars는 SQLContext 객체로 SQL 쿼리를 관리합니다. 컨텍스트에는 DataFrame과 LazyFrame의 식별자 이름과 그에 대응하는 데이터셋의 매핑이 들어 있어요. 아래 예제는 SQLContext를 시작하는 모습입니다:
ctx = pl.SQLContext()
DataFrame 등록하기
SQLContext 초기화 시 DataFrame을 등록하는 방법은 여러 가지가 있습니다.
- 전역 네임스페이스의 모든
LazyFrame과DataFrame객체를 등록한다. - 딕셔너리 매핑 또는 kwargs로 명시적으로 등록한다.
df = pl.DataFrame({"a": [1, 2, 3]})
lf = pl.LazyFrame({"b": [4, 5, 6]})
# Register all dataframes in the global namespace: registers both "df" and "lf"
ctx = pl.SQLContext(register_globals=True)
# Register an explicit mapping of identifier name to frame
ctx = pl.SQLContext(frames={"table_one": df, "table_two": lf})
# Register frames using kwargs; dataframe df as "df" and lazyframe lf as "lf"
ctx = pl.SQLContext(df=df, lf=lf)
Pandas DataFrame은 먼저 Polars로 변환한 뒤 등록할 수도 있습니다.
import pandas as pd
df_pandas = pd.DataFrame({"c": [7, 8, 9]})
ctx = pl.SQLContext(df_pandas=pl.from_pandas(df_pandas))
Pandas
Numpy로 백업된 Pandas DataFrame을 변환하면 비용이 꽤 들 수 있어요. 하지만 Pandas DataFrame이 이미 Arrow로 백업돼 있다면 변환 비용이 훨씬 저렴하고(어떤 경우엔 거의 공짜에 가깝습니다) 거의 없을 수 있어요.
SQLContext가 초기화된 뒤에는 추가 DataFrame을 등록하거나 기존 DataFrame을 해제할 수 있습니다.
registerregister_globalsregister_manyunregister
쿼리 실행과 결과 수집
SQL 쿼리는 항상 lazy 모드로 실행되어 쿼리 플래닝 최적화의 전체 세트를 활용합니다. 그래서 결과를 수집하는 방법은 두 가지입니다.
SQLContext에서eager파라미터를 True로 설정한다. 그러면execute호출 결과인 LazyFrame을 Polars가 자동으로 collect합니다.execute로 쿼리를 실행할 때eager를 True로 설정하거나,collect로 결과를 명시적으로 수집한다.
SQL 쿼리는 SQLContext에 execute를 호출해 실행합니다.
pokemon = pl.scan_csv("docs/assets/data/pokemon.csv")
with pl.SQLContext(register_globals=True, eager=True) as ctx:
df_small = ctx.execute("SELECT * from pokemon LIMIT 5")
print(df_small)
shape: (5, 13)
┌─────┬───────────────────────┬────────┬────────┬───┬─────────┬───────┬────────────┬───────────┐
│ # ┆ Name ┆ Type 1 ┆ Type 2 ┆ … ┆ Sp. Def ┆ Speed ┆ Generation ┆ Legendary │
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ str ┆ str ┆ ┆ i64 ┆ i64 ┆ i64 ┆ bool │
╞═════╪═══════════════════════╪════════╪════════╪═══╪═════════╪═══════╪════════════╪═══════════╡
│ 1 ┆ Bulbasaur ┆ Grass ┆ Poison ┆ … ┆ 65 ┆ 45 ┆ 1 ┆ false │
│ 2 ┆ Ivysaur ┆ Grass ┆ Poison ┆ … ┆ 80 ┆ 60 ┆ 1 ┆ false │
│ 3 ┆ Venusaur ┆ Grass ┆ Poison ┆ … ┆ 100 ┆ 80 ┆ 1 ┆ false │
│ 3 ┆ VenusaurMega Venusaur ┆ Grass ┆ Poison ┆ … ┆ 120 ┆ 80 ┆ 1 ┆ false │
│ 4 ┆ Charmander ┆ Fire ┆ null ┆ … ┆ 50 ┆ 65 ┆ 1 ┆ false │
└─────┴───────────────────────┴────────┴────────┴───┴─────────┴───────┴────────────┴───────────┘
여러 소스에서 쿼리 실행
여러 소스에서도 SQL 쿼리를 쉽게 실행할 수 있어요. 아래 예제에서는 다음을 등록합니다.
- CSV 파일 (lazy로 로드)
- NDJSON 파일 (lazy로 로드)
- Pandas DataFrame
그리고 SQL로 이들을 조인합니다. Lazy 읽기를 사용하면 파일에서 필요한 행과 컬럼만 불러올 수 있어요.
같은 방식으로 클라우드 데이터레이크(S3, Azure Data Lake)도 등록할 수 있습니다. PyArrow 데이터셋이 데이터레이크를 가리키면 Polars가 scan_pyarrow_dataset으로 읽어낼 수 있어요.
# Input data:
# products_masterdata.csv with schema {'product_id': Int64, 'product_name': String}
# products_categories.json with schema {'product_id': Int64, 'category': String}
# sales_data is a Pandas DataFrame with schema {'product_id': Int64, 'sales': Int64}
with pl.SQLContext(
products_masterdata=pl.scan_csv("docs/assets/data/products_masterdata.csv"),
products_categories=pl.scan_ndjson("docs/assets/data/products_categories.json"),
sales_data=pl.from_pandas(sales_data),
eager=True,
) as ctx:
query = """
SELECT
product_id,
product_name,
category,
sales
FROM
products_masterdata
LEFT JOIN products_categories USING (product_id)
LEFT JOIN sales_data USING (product_id)
"""
print(ctx.execute(query))
shape: (5, 4)
┌────────────┬──────────────┬────────────┬───────┐
│ product_id ┆ product_name ┆ category ┆ sales │
│ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ str ┆ i64 │
╞════════════╪══════════════╪════════════╪═══════╡
│ 4 ┆ Product D ┆ Category 2 ┆ 250 │
│ 5 ┆ Product E ┆ Category 3 ┆ 300 │
│ 1 ┆ Product A ┆ Category 1 ┆ 100 │
│ 2 ┆ Product B ┆ Category 1 ┆ 200 │
│ 3 ┆ Product C ┆ Category 2 ┆ 150 │
└────────────┴──────────────┴────────────┴───────┘
호환성
Polars는 완전한 SQL 스펙을 지원하지는 않지만, 가장 흔한 문장 유형의 부분 집합을 지원합니다.
방언
가능한 한 Polars는 PostgreSQL 구문 정의와 함수 동작을 따르는 것을 목표로 합니다.
예를 들어 지원되는 기능의 일부 목록은 이렇습니다.
CREATE문 작성:CREATE TABLE xxx AS ...WHERE,ORDER,LIMIT,GROUP BY,UNION,JOIN절을 포함한SELECT문 작성WITH tablename AS같은 공통 테이블 표현식(CTE) 작성- 쿼리 설명:
EXPLAIN SELECT ... - 등록된 테이블 나열:
SHOW TABLES - 테이블 삭제:
DROP TABLE [IF EXISTS] tablename - 테이블 비우기:
TRUNCATE TABLE [IF EXISTS] tablename
아직 지원되지 않는 기능은 다음과 같습니다.
INSERT,UPDATE,DELETE문ANALYZE같은 메타 쿼리
다음 섹션들에서는 각 문장에 대해 더 자세히 다룰 예정입니다.
더 알아보기 (Learn more)
SQLContext는 DataFrame·LazyFrame 매핑과 함께 공통 테이블 표현식도 추적해요.- SQL이 표현식 API로 번역되는 배경은 표현식과 컨텍스트 문서를 참고하세요.