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

# パフォーマンスガイド

> DataStore と pandas のパフォーマンス最適化のヒント

DataStore は、多くの処理で pandas より大幅に高いパフォーマンスを発揮します。このガイドでは、その理由と、ワークロードを最適化する方法について説明します。

<div id="why-faster">
  ## DataStore が高速な理由
</div>

<div id="sql-pushdown">
  ### 1. SQL プッシュダウン
</div>

処理はデータソース側にプッシュダウンされます：

```python theme={null}
# pandas: すべてのデータを読み込んでからメモリ内でフィルタリング
df = pd.read_csv("huge.csv")       # 10GBを読み込む
df = df[df['year'] == 2024]        # Pythonでフィルタリング

# DataStore: データソースでフィルタリング
ds = pd.read_csv("huge.csv")       # メタデータのみ
ds = ds[ds['year'] == 2024]        # SQLでフィルタリング
df = ds.to_df()                    # フィルタリング済みデータのみ読み込む
```

<div id="column-pruning">
  ### 2. カラムプルーニング
</div>

必要なカラムのみが読み込まれます:

```python theme={null}
# DataStore: name、age カラムのみを読み取る
ds = pd.read_parquet("wide_table.parquet")
result = ds.select('name', 'age').to_df()

# vs pandas: 100カラムすべてを読み取ってから選択する
```

<div id="lazy-evaluation">
  ### 3. 遅延評価
</div>

複数の操作が 1 つのクエリにまとめてコンパイルされます:

```python theme={null}
# DataStore: 最適化された単一のSQLクエリ
result = (ds
    .filter(ds['amount'] > 100)
    .groupby('region')
    .agg({'amount': 'sum'})
    .sort('sum', ascending=False)
    .head(10)
    .to_df()
)

# 変換後:
# SELECT region, SUM(amount) FROM data
# WHERE amount > 100
# GROUP BY region ORDER BY sum DESC LIMIT 10
```

***

<div id="benchmark">
  ## ベンチマーク: DataStore と pandas
</div>

<div id="test-environment">
  ### テスト環境
</div>

* データ: 1,000万行
* ハードウェア: 一般的なノートPC
* ファイル形式: CSV

<div id="results">
  ### 結果
</div>

| 操作               | pandas (ms) | DataStore (ms) | 優位                     |
| ---------------- | ----------- | -------------- | ---------------------- |
| GroupBy 件数       | 347         | 17             | **DataStore (19.93x)** |
| 複合操作             | 1,535       | 234            | **DataStore (6.56x)**  |
| 複雑なパイプライン        | 2,047       | 380            | **DataStore (5.39x)**  |
| 複数フィルタ+ソート+Head  | 1,963       | 366            | **DataStore (5.36x)**  |
| フィルタ+ソート+Head    | 1,537       | 350            | **DataStore (4.40x)**  |
| Head/Limit       | 166         | 45             | **DataStore (3.69x)**  |
| 超複雑 (10個以上の操作)   | 1,070       | 338            | **DataStore (3.17x)**  |
| GroupBy 集計       | 406         | 141            | **DataStore (2.88x)**  |
| Select+フィルタ+ソート  | 1,217       | 443            | **DataStore (2.75x)**  |
| フィルタ+GroupBy+ソート | 466         | 184            | **DataStore (2.53x)**  |
| フィルタ+Select+ソート  | 1,285       | 533            | **DataStore (2.41x)**  |
| ソート (単一)         | 1,742       | 1,197          | **DataStore (1.45x)**  |
| フィルタ (単一)        | 276         | 526            | 同等                     |
| ソート (複数)         | 947         | 1,477          | 同等                     |

<div id="insights">
  ### 主なポイント
</div>

1. **GroupBy 操作**: DataStore は最大 **19.93 倍高速**
2. **複雑なパイプライン**: DataStore は **5〜6 倍高速** (SQL プッシュダウンの効果)
3. **単純なスライス操作**: 性能は同程度で、差はごくわずか
4. **最適なユースケース**: groupby/aggregation を含む複数ステップの処理
5. **ゼロコピー**: `to_df()` ではデータ変換のオーバーヘッドが発生しない

***

<div id="when-datastore-wins">
  ## DataStore が効果を発揮するケース
</div>

<div id="heavy-aggregations">
  ### 高負荷な集計処理
</div>

```python theme={null}
# DataStore が真価を発揮: 19.93倍高速
result = ds.groupby('category')['amount'].sum()
```

<div id="complex-pipelines">
  ### 複雑なパイプライン
</div>

```python theme={null}
# DataStore が優れている: 5〜6倍高速
result = (ds
    .filter(ds['date'] >= '2024-01-01')
    .filter(ds['amount'] > 100)
    .groupby('region')
    .agg({'amount': ['sum', 'mean', 'count']})
    .sort('sum', ascending=False)
    .head(20)
)
```

<div id="large-file-processing">
  ### 大容量ファイルの処理
</div>

```python theme={null}
# DataStore: 必要なデータのみを読み込みます
ds = pd.read_parquet("huge_file.parquet")
result = ds.filter(ds['id'] == 12345).to_df()  # 高速！
```

<div id="multiple-column-operations">
  ### 複数カラムの操作
</div>

```python theme={null}
# DataStore: 単一のSQLに結合
ds['total'] = ds['price'] * ds['quantity']
ds['is_large'] = ds['total'] > 1000
ds = ds.filter(ds['is_large'])
```

***

<div id="when-pandas-wins">
  ## pandas と同程度の性能になる場合
</div>

ほとんどのケースでは、DataStore は pandas と同等以上の性能を発揮します。ただし、次のような特定のケースでは、pandas のほうがわずかに高速な場合があります。

<div id="small-datasets">
  ### 小規模なデータセット (1,000行未満)
</div>

```python theme={null}
# 非常に小さなデータセットの場合、どちらもオーバーヘッドは最小限
# パフォーマンスの差は無視できる
small_df = pd.DataFrame({'x': range(100)})
```

<div id="simple-slice-operations">
  ### 基本的なスライス操作
</div>

```python theme={null}
# 集計なしの単純なスライス操作
df = df[df['x'] > 10]  # pandasの方がわずかに高速
ds = ds[ds['x'] > 10]  # DataStoreは同等
```

<div id="custom-python-functions">
  ### カスタム Python のラムダ関数
</div>

```python theme={null}
# カスタムPythonコードにはpandasが必要
def complex_function(row):
    return custom_logic(row)

df['result'] = df.apply(complex_function, axis=1)
```

<Info>
  **重要**

  DataStore が「遅い」ケースでも、通常、パフォーマンスは **pandas とほぼ同等** で、実用上の差はほとんどありません。複雑な操作では、DataStore の利点がこうした限定的なケースを大きく上回ります。

  実行を細かく制御する方法については、[実行エンジンの設定](/ja/products/chdb/configuration/execution-engine) を参照してください。
</Info>

***

<div id="zero-copy">
  ## ゼロコピー DataFrameインテグレーション
</div>

DataStore は、pandas の DataFrame の読み書きに **ゼロコピー** を採用しています。これは、次のことを意味します。

```python theme={null}
# to_df() はデータをコピーしません - ゼロコピー操作です
result = ds.filter(ds['x'] > 10).to_df()  # データ変換のオーバーヘッドなし

# DataFrame から DataStore を作成する場合も同様
ds = DataStore(existing_df)  # データのコピーなし
```

**主なポイント:**

* `to_df()` は実質的にコストがかからず、シリアライゼーションやメモリコピーも発生しません
* pandas の DataFrame から DataStore を作成する処理は瞬時に完了します
* メモリは DataStore と pandas のビューの間で共有されます

***

<div id="tips">
  ## 最適化のヒント
</div>

<div id="use-performance-mode">
  ### 1. 負荷の高いワークロード向けにパフォーマンスモードを有効にする
</div>

集約処理が中心のワークロードで、pandas の出力フォーマット (行の順序、MultiIndex カラム、dtype の補正) を厳密に再現する必要がない場合は、最大のスループットを得るためにパフォーマンスモードを有効にします。

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

config.use_performance_mode()

# すべての操作がSQL優先実行となり、pandasのオーバーヘッドが発生しない:
# - 並列Parquet読み込み（preserve_orderなし）
# - 単一SQLによる集計（filter+groupbyを1クエリで処理）
# - 行順序保持のオーバーヘッドなし
# - MultiIndexなし、データ型補正なし
result = (ds
    .filter(ds['amount'] > 100)
    .groupby('region')
    .agg({'amount': ['sum', 'mean', 'count']})
)
```

**期待される改善**: filter+groupbyワークロードで最大2〜8倍高速化し、大規模なParquetファイルのメモリ使用量を削減します。

詳細は[パフォーマンスモード](/ja/products/chdb/configuration/performance-mode)を参照してください。

<div id="use-parquet">
  ### 2. CSVの代わりにParquetを使用する
</div>

```python theme={null}
# CSV: 低速、ファイル全体を読み込む
ds = pd.read_csv("data.csv")

# Parquet: 高速、列指向、圧縮済み
ds = pd.read_parquet("data.parquet")

# 一度変換すれば、永続的に恩恵を受けられる
df = pd.read_csv("data.csv")
df.to_parquet("data.parquet")
```

**期待される改善**: 読み取り速度が3〜10倍向上

<div id="filter-early">
  ### 3. 早い段階でフィルタする
</div>

```python theme={null}
# 良い例: 先にフィルタリングしてから集計する
result = (ds
    .filter(ds['date'] >= '2024-01-01')  # 早い段階でデータを絞り込む
    .groupby('category')['amount'].sum()
)

# 非効率な例: 全データを処理する
result = (ds
    .groupby('category')['amount'].sum()
    .filter(ds['sum'] > 1000)  # フィルタリングが遅すぎる
)
```

<div id="select-only-needed-columns">
  ### 4. 必要なカラムのみを選択する
</div>

```python theme={null}
# 良い例: カラムプルーニング
result = ds.select('name', 'amount').filter(ds['amount'] > 100)

# 非効率な例: 全カラムを読み込む
result = ds.filter(ds['amount'] > 100)  # 全カラムを読み込む
```

<div id="leverage-sql-aggregations">
  ### 5. SQLの集計を活用する
</div>

```python theme={null}
# GroupByはDataStoreが真価を発揮する場面です
# 最大20倍の高速化！
result = ds.groupby('category').agg({
    'amount': ['sum', 'mean', 'count', 'max'],
    'quantity': 'sum'
})
```

<div id="use-head">
  ### 6. 全件クエリの代わりに head() を使う
</div>

```python theme={null}
# サンプルだけが必要な場合は、結果全体を読み込まない
result = ds.filter(ds['type'] == 'A').head(100)  # LIMIT 100

# 大量の結果に対してはこの方法を避けること
# result = ds.filter(ds['type'] == 'A').to_df()  # すべてを読み込む
```

<div id="batch-operations">
  ### 7. バッチ処理
</div>

```python theme={null}
# 良い例: 単一実行
result = ds.filter(ds['x'] > 10).filter(ds['y'] < 100).to_df()

# 悪い例: 複数回実行
result1 = ds.filter(ds['x'] > 10).to_df()  # 実行
result2 = result1[result1['y'] < 100]       # 再実行
```

<div id="use-explain">
  ### 8. explain() を使って最適化する
</div>

```python theme={null}
# 実行前にクエリプランを確認する
query = ds.filter(...).groupby(...).agg(...)
query.explain()  # 操作がプッシュダウンされているか確認する

# 実行する
result = query.to_df()
```

***

<div id="profiling">
  ## ワークロードのプロファイリング
</div>

<div id="enable-profiling">
  ### プロファイリングを有効にする
</div>

```python theme={null}
from chdb.datastore.config import config, get_profiler

config.enable_profiling()

# ワークロードを実行する
result = your_pipeline()

# レポートを表示する
profiler = get_profiler()
profiler.report()
```

<div id="identify-bottlenecks">
  ### ボトルネックを特定する
</div>

```text theme={null}
パフォーマンスレポート
==================
ステップ                Duration    % 合計
----                    --------    -------
SQL execution           2.5s        62.5%     <- ボトルネック！
read_csv                1.2s        30.0%
その他                   0.3s        7.5%
```

<div id="compare-approaches">
  ### アプローチの比較
</div>

```python theme={null}
# アプローチ1のテスト
profiler.reset()
result1 = approach1()
time1 = profiler.get_steps()[-1]['duration_ms']

# アプローチ2のテスト
profiler.reset()
result2 = approach2()
time2 = profiler.get_steps()[-1]['duration_ms']

print(f"Approach 1: {time1:.0f}ms")
print(f"Approach 2: {time2:.0f}ms")
```

***

<div id="summary">
  ## ベストプラクティスのまとめ
</div>

| Practice            | Impact             |
| ------------------- | ------------------ |
| パフォーマンスモードを有効にする    | 集計ワークロードで 2～8 倍高速化 |
| Parquet ファイルを使用する   | 読み取りが 3～10 倍高速化    |
| 早い段階で絞り込む           | データ処理量を削減          |
| 必要なカラムだけを選択する       | I/O とメモリ使用量を削減     |
| GroupBy/集計を使用する     | 最大 20 倍高速化         |
| バッチ処理を使用する          | 繰り返し実行を回避          |
| 最適化の前にプロファイリングする    | 実際のボトルネックを特定       |
| explain() を使用する     | クエリ最適化を検証          |
| サンプルには head() を使用する | テーブル全体のスキャンを回避     |

***

<div id="decision">
  ## 早見表
</div>

| ワークロード                | 推奨                 |
| --------------------- | ------------------ |
| GroupBy/集約            | DataStore を使用      |
| 複雑な多段パイプライン           | DataStore を使用      |
| フィルター付きの大きなファイル       | DataStore を使用      |
| 単純なスライス操作             | どちらでも可 (性能は同程度)    |
| カスタム Python ラムダ関数     | pandas を使用するか、後で変換 |
| 非常に小さいデータ (\<1,000 行) | どちらでも可 (差はほぼありません) |

<Tip>
  最適なエンジンを自動選択するには、`config.set_execution_engine('auto')` (デフォルト) を使用します。
  集約ワークロードで最大のスループットを得るには、`config.use_performance_mode()` を使用します。
  詳細は [実行エンジン](/ja/products/chdb/configuration/execution-engine) と [パフォーマンスモード](/ja/products/chdb/configuration/performance-mode) を参照してください。
</Tip>
