메인 콘텐츠로 건너뛰기
DataStore는 pandas와 매우 높은 호환성을 갖추고 있지만, 알아두어야 할 중요한 차이점이 있습니다.

요약 표

AspectpandasDataStore
실행Eager (즉시 실행)Lazy (지연 실행)
반환 타입DataFrame/SeriesDataStore/ColumnExpr
행 순서유지됨유지됨(자동); 성능 모드에서는 보장되지 않음
inplace지원됨지원되지 않음
인덱스완전 지원단순화됨
메모리모든 데이터가 메모리에 있음데이터가 소스에 유지됨

1. 지연 실행 vs 즉시 실행

pandas (즉시 실행)

연산이 바로 실행됩니다:
import pandas as pd

df = pd.read_csv("data.csv")  # 전체 파일을 즉시 로드
result = df[df['age'] > 25]   # 즉시 필터링
grouped = result.groupby('city')['salary'].mean()  # 즉시 집계

DataStore (지연 실행)

연산은 결과가 필요할 때까지 지연됩니다:
from chdb import datastore as pd

ds = pd.read_csv("data.csv")  # 소스만 기록
result = ds[ds['age'] > 25]   # 필터만 기록
grouped = result.groupby('city')['salary'].mean()  # 연산만 기록

# 실행은 여기서 시작:
print(grouped)        # 출력 시 실행
df = grouped.to_df()  # 또는 pandas로 변환 시 실행

왜 중요한가

지연 실행은 다음과 같은 이점을 제공합니다:
  • 쿼리 최적화: 여러 작업이 하나의 SQL 쿼리로 컴파일됩니다
  • 컬럼 프루닝(Column pruning): 필요한 컬럼만 읽습니다
  • 필터 푸시다운(Filter pushdown): 필터를 소스에 적용합니다
  • 메모리 효율성: 필요하지 않은 데이터는 로드하지 않습니다

2. 반환 타입

pandas

df['col']           # pd.Series 반환
df[['a', 'b']]      # pd.DataFrame 반환
df[df['x'] > 10]    # pd.DataFrame 반환
df.groupby('x')     # DataFrameGroupBy 반환

DataStore

ds['col']           # ColumnExpr 반환 (지연 실행)
ds[['a', 'b']]      # DataStore 반환 (지연 실행)
ds[ds['x'] > 10]    # DataStore 반환 (지연 실행)
ds.groupby('x')     # LazyGroupBy 반환

pandas 타입으로 변환하기

# pandas DataFrame 가져오기
df = ds.to_df()
df = ds.to_pandas()

# 컬럼에서 pandas Series 가져오기
series = ds['col'].to_pandas()

# 또는 실행 트리거
print(ds)  # 표시를 위해 자동으로 변환

3. 실행 트리거

DataStore는 실제 값이 필요해지는 시점에 실행됩니다:
트리거예시참고
print() / repr()print(ds)출력하려면 데이터가 필요합니다
len()len(ds)행 수가 필요합니다
.columnsds.columns컬럼 이름이 필요합니다
.dtypesds.dtypes타입 정보가 필요합니다
.shapeds.shape차원 정보가 필요합니다
.valuesds.values실제 데이터가 필요합니다
.indexds.index인덱스가 필요합니다
to_df()ds.to_df()명시적으로 변환합니다
반복for row in ds순회가 필요합니다
equals()ds.equals(other)비교가 필요합니다

지연 실행로 유지되는 작업

작업반환값
filter()DataStore
select()DataStore
sort()DataStore
groupby()LazyGroupBy
join()DataStore
ds['col']ColumnExpr
ds[['a', 'b']]DataStore
ds[condition]DataStore

4. 행 순서

pandas

행의 순서는 항상 유지됩니다:
df = pd.read_csv("data.csv")
print(df.head())  # 항상 파일과 동일한 순서 유지

DataStore

대부분의 작업에서 행 순서는 자동으로 유지됩니다:
ds = pd.read_csv("data.csv")
print(ds.head())  # 파일 순서와 일치

# 필터 적용 후에도 순서 유지
ds_filtered = ds[ds['age'] > 25]  # pandas와 동일한 순서
DataStore는 pandas와의 순서 일관성을 보장하기 위해 내부적으로 원래 행 위치를 rowNumberInAllBlocks()를 사용해 자동으로 추적합니다.

순서가 유지되는 경우

  • 파일 소스(CSV, Parquet, JSON 등)
  • pandas DataFrame 소스
  • 필터링 작업
  • 컬럼 선택
  • 명시적으로 sort() 또는 sort_values()를 수행한 후
  • 순서를 결정하는 작업(nlargest(), nsmallest(), head(), tail())

순서가 달라질 수 있는 경우

  • groupby() 집계 후(sort_values()를 사용하면 일관된 순서를 유지할 수 있습니다)
  • 특정 join 유형으로 merge() / join()을 수행한 후
  • 성능 모드(config.use_performance_mode())에서는 어떤 작업에서도 행 순서가 보장되지 않습니다. 성능 모드를 참조하십시오.

5. inplace 매개변수 미지원

pandas

df.drop(columns=['col'], inplace=True)  # df를 직접 수정
df.fillna(0, inplace=True)              # df를 직접 수정
df.rename(columns={'old': 'new'}, inplace=True)

DataStore

inplace=True는 지원되지 않습니다. 결과는 항상 다시 할당하세요:
ds = ds.drop(columns=['col'])           # 새로운 DataStore를 반환합니다
ds = ds.fillna(0)                       # 새로운 DataStore를 반환합니다
ds = ds.rename(columns={'old': 'new'})  # 새로운 DataStore를 반환합니다

왜 inplace를 지원하지 않나요?

DataStore는 다음을 지원하기 위해 불변 연산을 사용합니다:
  • 쿼리 작성(lazy evaluation)
  • 스레드 안전성
  • 디버깅 용이성
  • 더 깔끔한 코드

6. 인덱스 지원

pandas

모든 인덱스를 지원합니다:
df = df.set_index('id')
df.loc['user123']           # 레이블 기반 접근
df.loc['a':'z']             # 레이블 기반 슬라이싱
df.reset_index()
df.index.name = 'user_id'

DataStore

간편한 인덱스 지원:
# 기본 작업 가능
ds.loc[0:10]               # 정수 위치
ds.iloc[0:10]              # DataStore에서 loc과 동일

# pandas 스타일 인덱스 작업의 경우 먼저 변환
df = ds.to_df()
df = df.set_index('id')
df.loc['user123']

DataStore에서는 소스가 중요합니다

  • DataFrame 소스: pandas 인덱스가 유지됩니다
  • File 소스: 단순한 정수 인덱스를 사용합니다

7. 비교 방식

pandas와의 비교

pandas는 DataStore 객체를 인식하지 않습니다:
import pandas as pd
from chdb import datastore as ds

pdf = pd.DataFrame({'a': [1, 2, 3]})
dsf = ds.DataFrame({'a': [1, 2, 3]})

# 예상대로 동작하지 않음
pdf == dsf  # pandas는 DataStore를 인식하지 못함

# 해결 방법: DataStore를 pandas로 변환
pdf.equals(dsf.to_pandas())  # True

equals() 사용하기

# DataStore.equals()도 작동합니다
dsf.equals(pdf)  # pandas DataFrame과 비교합니다

8. 타입 추론

pandas

numpy/pandas의 타입을 사용합니다:
df['col'].dtype  # int64, float64, object, datetime64, 등

DataStore

ClickHouse 타입을 사용할 수 있습니다:
ds['col'].dtype  # Int64, Float64, String, DateTime, etc.

# pandas로 변환 시 타입이 변환됩니다
df = ds.to_df()
df['col'].dtype  # 이제 pandas 타입

명시적 형 변환

# 특정 유형으로 강제 변환
ds['col'] = ds['col'].astype('int64')

9. 메모리 모델

pandas

모든 데이터가 메모리에 상주합니다:
df = pd.read_csv("huge.csv")  # 메모리에 10GB!

DataStore

데이터는 필요할 때까지 원본에 그대로 유지됩니다:
ds = pd.read_csv("huge.csv")  # 메타데이터뿐
ds = ds.filter(ds['year'] == 2024)  # 여전히 메타데이터뿐

# 필터링된 결과만 불러옵니다
df = ds.to_df()  # 이제 1GB 정도일 수도 있음

10. 오류 메시지

다양한 오류 발생 원인

  • pandas 오류: pandas 라이브러리에서 발생
  • DataStore 오류: chDB 또는 ClickHouse에서 발생
# ClickHouse 스타일의 오류가 표시될 수 있습니다
# "Code: 62. DB::Exception: Syntax error..."

디버깅 팁

# 디버깅을 위해 SQL 확인
print(ds.to_sql())

# 실행 계획 확인
ds.explain()

# 디버그 로깅 활성화
from chdb.datastore.config import config
config.enable_debug()

마이그레이션 체크리스트

pandas에서 마이그레이션할 때:
  • import 문 변경
  • inplace=True 매개변수 제거
  • pandas DataFrame이 필요한 경우 to_df()를 명시적으로 추가
  • 행 순서가 중요하면 정렬 추가
  • 비교 테스트에는 to_pandas() 사용
  • 실제와 유사한 데이터 크기로 테스트

빠른 참고

pandasDataStore
df[condition]동일(DataStore 반환)
df.groupby()동일(LazyGroupBy 반환)
df.drop(inplace=True)ds = ds.drop()
df.equals(other)ds.to_pandas().equals(other)
df.loc['label']ds.to_df().loc['label']
print(df)동일(실행 트리거)
len(df)동일(실행 트리거)
마지막 수정일 2026년 6월 10일