Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

mode Performance (compat_mode)

DataStore propose deux modes de compatibilité qui déterminent si la sortie est formatée pour la compatibilité avec pandas ou optimisée pour les performances du SQL brut.

Vue d’ensemble

Mode compat_mode value Description
Pandas (par défaut) "pandas" Compatibilité complète avec le comportement de pandas. Ordre des lignes conservé, MultiIndex, set_index, corrections de dtype, départage en tri stable, wrappers -If/isNaN.
Performance "performance" Exécution orientée SQL. Tout le surcoût lié à la compatibilité avec pandas est supprimé. Débit maximal, mais les résultats peuvent présenter des différences structurelles par rapport à pandas.

Ce que désactive le mode Performance

Surcoût Comportement du mode Pandas Comportement du mode Performance
Préservation de l'ordre des lignes Injection de _row_id, rowNumberInAllBlocks(), sous-requêtes __orig_row_num__ Désactivé — l'ordre des lignes n'est pas garanti
Départage des ex æquo dans un tri stable rowNumberInAllBlocks() ASC ajouté à ORDER BY Désactivé — les ex æquo peuvent apparaître dans un ordre arbitraire
preserve_order de Parquet input_format_parquet_preserve_order=1 Désactivé — lecture parallèle de Parquet autorisée
ORDER BY automatique de GroupBy ORDER BY group_key ajouté (valeur par défaut de pandas : sort=True) Désactivé — les groupes sont renvoyés dans un ordre arbitraire
WHERE dropna de GroupBy WHERE key IS NOT NULL ajouté (valeur par défaut de pandas : dropna=True) Désactivé — les groupes NULL sont inclus
set_index de GroupBy Les clés de groupe sont définies comme index Désactivé — les clés de groupe restent des colonnes
Colonnes MultiIndex agg({'col': ['sum','mean']}) renvoie des colonnes MultiIndex Désactivé — noms de colonnes plats (col_sum, col_mean)
Wrappers -If/isNaN sumIf(col, NOT isNaN(col)) pour skipna Désactivé — sum(col) simple (ClickHouse ignore nativement NULL)
toInt64 sur count toInt64(count()) pour correspondre au type int64 de pandas Désactivé — renvoie le Dtype SQL natif
fillna(0) pour une somme entièrement NaN La somme de valeurs toutes à NaN renvoie 0 (comportement de pandas) Désactivé — renvoie NULL
Corrections de Dtype abs() non signé→signé, etc. Désactivé — Dtypes SQL natifs
Préservation de l'index Restaure l'index d'origine après l'exécution SQL Désactivé
first()/last() argMin/argMax(col, rowNumberInAllBlocks()) any(col) / anyLast(col) — plus rapide mais non-deterministic
Agrégation en une seule requête SQL Le groupby de ColumnExpr matérialise un DataFrame intermédiaire Injecte LazyGroupByAgg dans la chaîne d'opérations Lazy — une seule SQL query

Activation du mode Performance

Utilisation de l’objet de configuration

from chdb.datastore.config import config

# Enable performance mode
config.use_performance_mode()

# Back to pandas compatibility
config.use_pandas_compat()

# Check current mode
print(config.compat_mode)  # 'pandas' or 'performance'

Utilisation des fonctions au niveau du module

from chdb.datastore.config import set_compat_mode, CompatMode, is_performance_mode

# Enable performance mode
set_compat_mode(CompatMode.PERFORMANCE)

# Check
print(is_performance_mode())  # True

# Back to default
set_compat_mode(CompatMode.PANDAS)

Utilisation des imports simplifiés

from chdb import use_performance_mode, use_pandas_compat

use_performance_mode()
# ... high-performance operations ...
use_pandas_compat()

Quand utiliser le mode Performance

Utilisez le mode Performance lorsque :

  • vous traitez de grands jeux de données (de centaines de milliers à plusieurs millions de lignes)
  • vous exécutez des workloads à forte agrégation (groupby, sum, mean, count)
  • l'ordre des lignes n'a pas d'importance (par exemple pour des résultats agrégés, des rapports ou des tableaux de bord)
  • vous voulez un débit SQL maximal avec un minimum d'overhead
  • la consommation mémoire est un enjeu (lecture parallèle de Parquet, sans DataFrame intermédiaire)

Restez en mode pandas lorsque :

  • vous avez besoin du comportement exact de pandas (ordre des lignes, MultiIndex, dtypes)
  • vous dépendez de first()/last() pour renvoyer la véritable première/dernière ligne
  • vous utilisez shift(), diff(), cumsum() qui dépendent de l'ordre des lignes
  • vous écrivez des tests qui comparent les résultats de DataStore à ceux de pandas

Différences de comportement

Ordre des lignes

En mode performance, l’ordre des lignes n’est pas garanti pour quelque opération que ce soit. Cela inclut :

  • Résultats de filtrage
  • Résultats d’agrégation GroupBy
  • head() / tail() sans sort_values() explicite
  • Agrégations first() / last()

Si vous avez besoin de résultats ordonnés, ajoutez un sort_values() explicite :

config.use_performance_mode()

ds = pd.read_csv("data.csv")

# Unordered (fast)
result = ds.groupby("region")["revenue"].sum()

# Ordered (still fast, just adds ORDER BY)
result = ds.groupby("region")["revenue"].sum().sort_values()

Résultats de GroupBy

Aspect mode Pandas mode Performance
Emplacement de la clé de groupe Index (via set_index) Colonne classique
Ordre des groupes Trié par clé (par défaut) Ordre arbitraire
Groupes NULL Exclus (par défaut dropna=True) Inclus
Format des colonnes MultiIndex pour les agrégations multiples Noms plats (col_func)
first()/last() Déterministe (ordre des lignes) Non déterministe (any()/anyLast())

Agrégation

config.use_performance_mode()

# Sum of all-NaN group returns NULL (not 0)
# Count returns native uint64 (not forced int64)
# No -If wrappers: sum() instead of sumIf()
result = ds.groupby("cat")["val"].sum()

Exécution en une seule requête SQL

En mode performance, l’agrégation groupby sur ColumnExpr (par ex., ds[condition].groupby('col')['val'].sum()) est exécutée comme une seule requête SQL, au lieu du processus en deux étapes utilisé en mode pandas :

config.use_performance_mode()

# Pandas mode: two SQL queries (filter → materialize → groupby)
# Performance mode: one SQL query (WHERE + GROUP BY in same query)
result = ds[ds["rating"] > 3.5].groupby("category")["revenue"].sum()

# Generated SQL (single query):
# SELECT category, sum(revenue) FROM data WHERE rating > 3.5 GROUP BY category

Cela évite la matérialisation intermédiaire du DataFrame et peut réduire considérablement l’utilisation de la mémoire ainsi que le temps d’exécution.


Comparaison avec le moteur d’exécution

Le mode Performance (compat_mode) et le moteur d’exécution (execution_engine) sont deux axes de configuration indépendants :

Configuration Contrôle Valeurs
execution_engine Quel moteur exécute le calcul auto, chdb, pandas
compat_mode Si la sortie doit être reformatée pour assurer la compatibilité avec pandas pandas, performance

Définir compat_mode='performance' définit automatiquement execution_engine='chdb', car le mode Performance est conçu pour l’exécution SQL.

from chdb.datastore.config import config

# These are independent
config.use_chdb()              # Force chDB engine, keep pandas compat
config.use_performance_mode()  # Force chDB + remove pandas overhead

Test en mode Performance

Lors de la rédaction de tests en mode Performance, les résultats peuvent différer de ceux de pandas en ce qui concerne l’ordre des lignes et le format structurel. Utilisez les stratégies suivantes :

Tri puis comparaison (agrégations, filtres)

# Sort both sides by the same columns before comparing
ds_result = ds.groupby("cat")["val"].sum()
pd_result = pd_df.groupby("cat")["val"].sum()

ds_sorted = ds_result.sort_index()
pd_sorted = pd_result.sort_index()
np.testing.assert_array_equal(ds_sorted.values, pd_sorted.values)

Contrôle de la plage de valeurs (première/dernière)

# first() with any() returns an arbitrary element from the group
result = ds.groupby("cat")["val"].first()
for group_key in groups:
    assert result.loc[group_key] in group_values[group_key]

Schéma et comptage (LIMIT sans ORDER BY)

# head() without sort_values: row set is non-deterministic
result = ds.head(5)
assert len(result) == 5
assert set(result.columns) == expected_columns

Bonnes pratiques

1. Activez-le dès le début de votre script

from chdb.datastore.config import config

config.use_performance_mode()

# All subsequent operations benefit
ds = pd.read_parquet("data.parquet")
result = ds[ds["amount"] > 100].groupby("region")["amount"].sum()

2. Ajoutez un tri explicite lorsque l’ordre est important

# For display or downstream processing that expects order
result = (ds
    .groupby("region")["revenue"].sum()
    .sort_values(ascending=False)
)

3. À utiliser pour les charges de travail de traitement par lots/ETL

config.use_performance_mode()

# ETL pipeline — order doesn't matter, throughput does
summary = (ds
    .filter(ds["date"] >= "2024-01-01")
    .groupby(["region", "product"])
    .agg({"revenue": "sum", "quantity": "sum", "rating": "mean"})
)
summary.to_df().to_parquet("summary.parquet")

4. Basculer entre les modes au sein d’une session

# Performance mode for heavy computation
config.use_performance_mode()
aggregated = ds.groupby("cat")["val"].sum()

# Back to pandas mode for exact-match comparison
config.use_pandas_compat()
detailed = ds[ds["val"] > 100].head(10)

Navigation