> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-fix-nav-issues.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# DataStore I/O 작업

> DataStore를 사용한 데이터 읽기 및 쓰기 - 지원되는 모든 포맷 및 대상

DataStore는 다양한 파일 포맷과 데이터 소스의 데이터를 읽고 쓸 수 있습니다.

<div id="reading">
  ## 데이터 읽기
</div>

<div id="read-csv">
  ### CSV 파일
</div>

```python theme={null}
read_csv(filepath_or_buffer, sep=',', header='infer', names=None, 
         usecols=None, dtype=None, nrows=None, skiprows=None,
         compression=None, encoding=None, **kwargs)
```

**예시:**

```python theme={null}
from chdb import datastore as pd

# 기본 CSV 읽기
ds = pd.read_csv("data.csv")

# With options
ds = pd.read_csv(
    "data.csv",
    sep=";",                    # 사용자 정의 구분자
    header=0,                   # 헤더 행 인덱스
    names=['a', 'b', 'c'],      # 사용자 정의 컬럼 이름
    usecols=['a', 'b'],         # 특정 컬럼만 읽기
    dtype={'a': 'Int64'},       # 데이터 타입 지정
    nrows=1000,                 # 처음 1000개 행만 읽기
    skiprows=1,                 # 첫 번째 행 건너뛰기
    compression='gzip',         # 압축 파일
    encoding='utf-8'            # 인코딩
)

# URL에서 읽기
ds = pd.read_csv("https://example.com/data.csv")
```

<div id="read-parquet">
  ### Parquet 파일
</div>

대규모 데이터셋에 권장되며, 압축 효율이 더 좋은 컬럼형 포맷입니다.

```python theme={null}
read_parquet(path, columns=None, **kwargs)
```

**예시:**

```python theme={null}
# 기본 Parquet 읽기
ds = pd.read_parquet("data.parquet")

# 특정 컬럼만 읽기 (효율적 - 필요한 데이터만 읽음)
ds = pd.read_parquet("data.parquet", columns=['col1', 'col2', 'col3'])

# S3에서 읽기
ds = pd.read_parquet("s3://bucket/data.parquet")
```

<div id="read-json">
  ### JSON 파일
</div>

```python theme={null}
read_json(path_or_buf, orient=None, lines=False, **kwargs)
```

**예시:**

```python theme={null}
# 표준 JSON
ds = pd.read_json("data.json")

# JSON Lines (줄바꿈 구분)
ds = pd.read_json("data.jsonl", lines=True)

# 특정 방향(orientation)을 지정한 JSON
ds = pd.read_json("data.json", orient='records')
```

<div id="read-excel">
  ### Excel 파일
</div>

```python theme={null}
read_excel(io, sheet_name=0, header=0, names=None, **kwargs)
```

**예시:**

```python theme={null}
# 첫 번째 시트 읽기
ds = pd.read_excel("data.xlsx")

# 특정 시트 읽기
ds = pd.read_excel("data.xlsx", sheet_name="Sheet1")
ds = pd.read_excel("data.xlsx", sheet_name=2)  # 세 번째 시트

# 여러 시트 읽기 (dict 반환)
sheets = pd.read_excel("data.xlsx", sheet_name=['Sheet1', 'Sheet2'])
```

<div id="read-sql">
  ### SQL 데이터베이스
</div>

```python theme={null}
read_sql(sql, con, **kwargs)
```

**예시:**

```python theme={null}
# SQL 쿼리에서 읽기
ds = pd.read_sql("SELECT * FROM users", connection)
ds = pd.read_sql("SELECT * FROM orders WHERE date > '2024-01-01'", connection)
```

<div id="read-other">
  ### 기타 포맷
</div>

```python theme={null}
# Feather (Arrow)
ds = pd.read_feather("data.feather")

# ORC
ds = pd.read_orc("data.orc")

# Pickle
ds = pd.read_pickle("data.pkl")

# 고정 너비 형식
ds = pd.read_fwf("data.txt", widths=[10, 20, 15])

# HTML 테이블
ds = pd.read_html("https://example.com/table.html")[0]
```

***

<div id="writing">
  ## 데이터 쓰기
</div>

<div id="to-csv">
  ### to\_csv
</div>

CSV 포맷으로 내보냅니다.

```python theme={null}
to_csv(path_or_buf=None, sep=',', na_rep='', header=True, 
       index=True, mode='w', compression=None, **kwargs)
```

**예시:**

```python theme={null}
ds = pd.read_parquet("data.parquet")

# 기본 내보내기
ds.to_csv("output.csv")

# With options
ds.to_csv(
    "output.csv",
    sep=";",                    # 사용자 지정 구분자
    index=False,                # 인덱스 미포함
    header=True,                # 헤더 포함
    na_rep='NULL',              # NaN을 'NULL'로 표시
    compression='gzip'          # 출력 압축
)

# 문자열로 변환
csv_string = ds.to_csv()
```

<div id="to-parquet">
  ### to\_parquet
</div>

Parquet 포맷으로 내보냅니다(대용량 데이터에 권장됨).

```python theme={null}
to_parquet(path, engine='pyarrow', compression='snappy', **kwargs)
```

**예시:**

```python theme={null}
# 기본 내보내기
ds.to_parquet("output.parquet")

# 압축 옵션 사용
ds.to_parquet("output.parquet", compression='gzip')
ds.to_parquet("output.parquet", compression='zstd')

# 파티션된 출력
ds.to_parquet(
    "output/",
    partition_cols=['year', 'month']
)
```

<div id="to-json">
  ### to\_json
</div>

JSON 포맷으로 내보냅니다.

```python theme={null}
to_json(path_or_buf=None, orient='records', lines=False, **kwargs)
```

**예시:**

```python theme={null}
# 표준 JSON (레코드 배열)
ds.to_json("output.json", orient='records')

# JSON Lines (한 줄에 JSON 객체 하나)
ds.to_json("output.jsonl", lines=True)

# 다양한 orient 옵션
ds.to_json("output.json", orient='split')    # {columns, data, index}
ds.to_json("output.json", orient='records')  # [{col: val}, ...]
ds.to_json("output.json", orient='columns')  # {col: {idx: val}}

# 문자열로 변환
json_string = ds.to_json()
```

<div id="to-excel">
  ### to\_excel
</div>

Excel 포맷으로 내보냅니다.

```python theme={null}
to_excel(excel_writer, sheet_name='Sheet1', index=True, **kwargs)
```

**예시:**

```python theme={null}
# 단일 시트
ds.to_excel("output.xlsx")
ds.to_excel("output.xlsx", sheet_name="Data", index=False)

# 여러 시트
with pd.ExcelWriter("output.xlsx") as writer:
    ds1.to_excel(writer, sheet_name="Sales")
    ds2.to_excel(writer, sheet_name="Inventory")
```

<div id="to-sql-method">
  ### to\_sql
</div>

SQL 데이터베이스로 내보내거나 SQL 문자열을 만듭니다.

```python theme={null}
to_sql(name=None, con=None, schema=None, if_exists='fail', **kwargs)
```

**예시:**

```python theme={null}
# SQL 쿼리 생성 (실행 없음)
sql = ds.to_sql()
print(sql)
# SELECT ...
# FROM ...
# WHERE ...

# 데이터베이스에 쓰기
ds.to_sql("table_name", connection, if_exists='replace')
```

<div id="to-other">
  ### 기타 내보내기 방법
</div>

```python theme={null}
# pandas DataFrame으로 변환
df = ds.to_df()
df = ds.to_pandas()

# Arrow Table로 변환
table = ds.to_arrow()

# NumPy 배열로 변환
arr = ds.to_numpy()

# 딕셔너리로 변환
d = ds.to_dict()
d = ds.to_dict(orient='records')  # 딕셔너리의 리스트
d = ds.to_dict(orient='list')     # 리스트의 딕셔너리

# 레코드로 변환 (튜플의 리스트)
records = ds.to_records()

# 문자열로 변환
s = ds.to_string()
s = ds.to_string(max_rows=100)

# Markdown으로 변환
md = ds.to_markdown()

# HTML로 변환
html = ds.to_html()

# LaTeX로 변환
latex = ds.to_latex()

# 클립보드로 복사
ds.to_clipboard()

# pickle로 저장
ds.to_pickle("output.pkl")

# feather로 저장
ds.to_feather("output.feather")
```

***

<div id="format-comparison">
  ## 파일 포맷 비교
</div>

| 포맷          | 읽기 속도 | 쓰기 속도 | 파일 크기 | 스키마   | 가장 적합한 용도             |
| ----------- | ----- | ----- | ----- | ----- | --------------------- |
| **Parquet** | 빠름    | 빠름    | 작음    | 있음    | 대규모 데이터셋, 분석          |
| **CSV**     | 보통    | 빠름    | 큼     | 없음    | 호환성, 단순한 데이터          |
| **JSON**    | 느림    | 보통    | 큼     | 부분 지원 | API, 중첩 데이터           |
| **Excel**   | 느림    | 느림    | 보통    | 부분 지원 | 비기술 사용자와 공유           |
| **Feather** | 매우 빠름 | 매우 빠름 | 보통    | 있음    | 프로세스 간 데이터 교환, pandas |

<div id="recommendations">
  ### 권장 사항
</div>

1. **분석 워크로드용:** Parquet를 사용합니다
   * 컬럼형 포맷이므로 필요한 컬럼만 읽을 수 있습니다
   * 압축 효율이 뛰어납니다
   * 데이터 타입이 유지됩니다

2. **데이터 교환용:** CSV 또는 JSON을 사용합니다
   * 범용 호환성이 높습니다
   * 사람이 읽기 쉽습니다

3. **pandas 상호 운용용:** Feather 또는 Arrow를 사용합니다
   * 직렬화가 가장 빠릅니다
   * 타입이 유지됩니다

***

<div id="compression">
  ## 압축 지원
</div>

<div id="read-compressed">
  ### 압축 파일 읽기
</div>

```python theme={null}
# 확장자에서 자동 감지
ds = pd.read_csv("data.csv.gz")
ds = pd.read_csv("data.csv.bz2")
ds = pd.read_csv("data.csv.xz")
ds = pd.read_csv("data.csv.zst")

# 명시적 압축
ds = pd.read_csv("data.csv", compression='gzip')
```

<div id="write-compressed">
  ### 압축 파일 쓰기
</div>

```python theme={null}
# 압축을 사용하는 CSV
ds.to_csv("output.csv.gz", compression='gzip')
ds.to_csv("output.csv.bz2", compression='bz2')

# Parquet (항상 압축됨)
ds.to_parquet("output.parquet", compression='snappy')  # 기본값
ds.to_parquet("output.parquet", compression='gzip')
ds.to_parquet("output.parquet", compression='zstd')    # 최고 압축률
ds.to_parquet("output.parquet", compression='lz4')     # 가장 빠름
```

<div id="compression-options">
  ### 압축 옵션
</div>

| 압축       | 속도    | 압축률   | 사용 사례       |
| -------- | ----- | ----- | ----------- |
| `snappy` | 매우 빠름 | 낮음    | Parquet 기본값 |
| `lz4`    | 매우 빠름 | 낮음    | 속도 우선       |
| `gzip`   | 보통    | 높음    | 호환성         |
| `zstd`   | 빠름    | 매우 높음 | 가장 뛰어난 균형   |
| `bz2`    | 느림    | 매우 높음 | 최대 압축       |

***

<div id="streaming">
  ## 스트리밍 I/O
</div>

메모리에 모두 올릴 수 없을 만큼 큰 파일의 경우:

<div id="chunked-read">
  ### 청크 단위 읽기
</div>

```python theme={null}
# 청크 단위로 읽기
for chunk in pd.read_csv("large.csv", chunksize=100000):
    # 각 청크 처리
    process(chunk)

# 이터레이터 사용
reader = pd.read_csv("large.csv", iterator=True)
chunk = reader.get_chunk(10000)
```

<div id="clickhouse-streaming">
  ### ClickHouse Streaming 사용
</div>

```python theme={null}
from chdb.datastore import DataStore

# 파일에서 스트리밍 - 전체를 메모리에 로드하지 않음
ds = DataStore.from_file("huge.parquet")

# 연산은 지연 실행 방식 - 필요한 것만 계산
result = ds.filter(ds['amount'] > 1000).head(100)
```

***

<div id="remote">
  ## 원격 데이터 소스
</div>

<div id="http">
  ### HTTP/HTTPS
</div>

```python theme={null}
# URL에서 읽기
ds = pd.read_csv("https://example.com/data.csv")
ds = pd.read_parquet("https://example.com/data.parquet")
```

<div id="s3">
  ### S3
</div>

```python theme={null}
from chdb.datastore import DataStore

# 익명 접근
ds = DataStore.uri("s3://bucket/data.parquet?nosign=true")

# 자격 증명 사용
ds = DataStore.from_s3(
    "s3://bucket/data.parquet",
    access_key_id="KEY",
    secret_access_key="SECRET"
)
```

<div id="cloud">
  ### GCS, Azure, HDFS
</div>

클라우드 스토리지 옵션은 [팩토리 메서드](/ko/products/chdb/datastore/factory-methods) 문서를 참조하십시오.

***

<div id="best-practices">
  ## 권장 사항
</div>

<div id="use-parquet-for-large-files">
  ### 1. 대용량 파일에는 Parquet를 사용하세요
</div>

```python theme={null}
# 성능 향상을 위해 CSV를 Parquet으로 변환
ds = pd.read_csv("large.csv")
ds.to_parquet("large.parquet")

# 이후 읽기 속도가 훨씬 빠름
ds = pd.read_parquet("large.parquet")
```

<div id="select-only-needed-columns">
  ### 2. 필요한 컬럼만 선택
</div>

```python theme={null}
# 효율적 - col1과 col2만 읽기
ds = pd.read_parquet("data.parquet", columns=['col1', 'col2'])

# 비효율적 - 모든 컬럼을 읽은 후 필터링
ds = pd.read_parquet("data.parquet")[['col1', 'col2']]
```

<div id="use-compression">
  ### 3. 압축 사용하기
</div>

```python theme={null}
# 파일 크기가 작아지고, I/O가 줄어들어 대개 더 빠릅니다
ds.to_parquet("output.parquet", compression='zstd')
```

<div id="batch-writes">
  ### 4. 배치 쓰기
</div>

```python theme={null}
# 루프 대신 한 번에 쓰기
result = process_all_data(ds)
result.to_parquet("output.parquet")

# 이렇게 하지 마세요 (비효율적)
for chunk in chunks:
    chunk.to_parquet(f"output_{i}.parquet")
```
