O DataStore tem dois modos de compatibilidade que determinam se a saída é formatada para compatibilidade com pandas ou otimizada para o desempenho de Raw SQL.
| Modo | valor de compat_mode | Descrição |
|---|
| Pandas (padrão) | "pandas" | Compatibilidade total com o comportamento do pandas. Ordem das linhas preservada, MultiIndex, set_index, correções de dtype, critérios de desempate em ordenação estável, wrappers -If/isNaN. |
| Performance | "performance" | Execução com foco em SQL. Toda a sobrecarga de compatibilidade com o pandas é removida. throughput máximo, mas os resultados podem diferir estruturalmente dos do pandas. |
O que o modo de desempenho desabilita
| Sobrecarga | Comportamento do modo Pandas | Comportamento do modo de desempenho |
|---|
| Preservação da ordem das linhas | Injeção de _row_id, rowNumberInAllBlocks(), subconsultas __orig_row_num__ | Desabilitado — a ordem das linhas não é garantida |
| Critério de desempate para ordenação estável | rowNumberInAllBlocks() ASC anexado a ORDER BY | Desabilitado — empates podem ficar em ordem arbitrária |
| Parquet preserve_order | input_format_parquet_preserve_order=1 | Desabilitado — leitura paralela de Parquet permitida |
| ORDER BY automático do GroupBy | ORDER BY group_key adicionado (padrão do pandas sort=True) | Desabilitado — os grupos são retornados em ordem arbitrária |
| WHERE dropna do GroupBy | WHERE key IS NOT NULL adicionado (padrão do pandas dropna=True) | Desabilitado — grupos NULL incluídos |
| set_index do GroupBy | Chaves de agrupamento definidas como índice | Desabilitado — as chaves de agrupamento permanecem como colunas |
| colunas MultiIndex | agg({'col': ['sum','mean']}) retorna colunas MultiIndex | Desabilitado — nomes de colunas simples (col_sum, col_mean) |
Wrappers -If/isNaN | sumIf(col, NOT isNaN(col)) para skipna | Desabilitado — sum(col) simples (o ClickHouse ignora NULL nativamente) |
toInt64 em count | toInt64(count()) para corresponder ao int64 do pandas | Desabilitado — o tipo SQL nativo é retornado |
fillna(0) para soma de todos os NaN | A soma de todos os NaN retorna 0 (comportamento do pandas) | Desabilitado — retorna NULL |
| Correções de tipo | abs() sem sinal→com sinal, etc. | Desabilitado — tipos SQL nativos |
| Preservação do índice | Restaura o índice original após a execução do SQL | Desabilitado |
first()/last() | argMin/argMax(col, rowNumberInAllBlocks()) | any(col) / anyLast(col) — mais rápido, mas não determinístico |
| Agregação em uma única consulta SQL | O groupby de ColumnExpr materializa um DataFrame intermediário | Injeta LazyGroupByAgg na cadeia de operações lazy — uma única consulta SQL |
Habilitando o modo de desempenho
from chdb.datastore.config import config
# Ativar modo de desempenho
config.use_performance_mode()
# Voltar para compatibilidade com pandas
config.use_pandas_compat()
# Verificar modo atual
print(config.compat_mode) # 'pandas' ou 'performance'
Usando funções no nível do módulo
from chdb.datastore.config import set_compat_mode, CompatMode, is_performance_mode
# Ativar modo de desempenho
set_compat_mode(CompatMode.PERFORMANCE)
# Verificar
print(is_performance_mode()) # True
# Voltar ao padrão
set_compat_mode(CompatMode.PANDAS)
Usando importações simplificadas
from chdb import use_performance_mode, use_pandas_compat
use_performance_mode()
# ... operações de alto desempenho ...
use_pandas_compat()
Ao ativar o modo de desempenho, o mecanismo de execução é definido automaticamente como chdb. Não é necessário chamar config.use_chdb() separadamente.
Quando usar o modo de desempenho
Use o modo de desempenho quando:
- Estiver processando grandes volumes de dados (de centenas de milhares a milhões de linhas)
- Estiver executando workloads com muita agregação (
groupby, sum, mean, count)
- A ordem das linhas não importar (por exemplo, resultados agregados, relatórios, dashboards)
- Quiser o máximo de throughput SQL com a menor sobrecarga possível
- O uso de memória for uma preocupação (leitura paralela de Parquet, sem DataFrames intermediários)
Permaneça no modo pandas quando:
- Precisar do comportamento exato do pandas (ordem das linhas, MultiIndex,
dtypes)
- Depender de
first()/last() para retornar de fato a primeira/última linha
- Usar
shift(), diff(), cumsum() que dependem da ordem das linhas
- Estiver escrevendo testes que comparam a saída do DataStore com o pandas
Diferenças de comportamento
No modo de desempenho, a ordem das linhas não é garantida em nenhuma operação. Isso inclui:
- Resultados de filtros
- Resultados de agregação de GroupBy
head() / tail() sem sort_values() explícito
- Agregações
first() / last()
Se precisar de resultados ordenados, adicione um sort_values() explícito:
config.use_performance_mode()
ds = pd.read_csv("data.csv")
# Sem ordenação (rápido)
result = ds.groupby("region")["revenue"].sum()
# Ordenado (ainda rápido, apenas adiciona ORDER BY)
result = ds.groupby("region")["revenue"].sum().sort_values()
| Aspecto | modo Pandas | modo de desempenho |
|---|
| Localização da chave de agrupamento | Índice (via set_index) | Coluna comum |
| Ordem dos grupos | Ordenada pela chave (padrão) | Arbitrária |
| Grupos NULL | Excluídos (padrão dropna=True) | Incluídos |
| Formato da coluna | MultiIndex para múltiplas agregações | Nomes simples (col_func) |
first()/last() | Determinístico (ordem das linhas) | Não determinístico (any()/anyLast()) |
config.use_performance_mode()
# Soma de grupo com todos NaN retorna NULL (não 0)
# Count retorna uint64 nativo (não int64 forçado)
# Sem wrappers -If: sum() em vez de sumIf()
result = ds.groupby("cat")["val"].sum()
No modo de desempenho, a agregação groupby de ColumnExpr (por exemplo, ds[condition].groupby('col')['val'].sum()) é executada como uma única consulta SQL, em vez do processo de duas etapas usado no modo pandas:
config.use_performance_mode()
# Modo Pandas: duas consultas SQL (filter → materialize → groupby)
# Modo performance: uma consulta SQL (WHERE + GROUP BY na mesma consulta)
result = ds[ds["rating"] > 3.5].groupby("category")["revenue"].sum()
# SQL gerado (consulta única):
# SELECT category, sum(revenue) FROM data WHERE rating > 3.5 GROUP BY category
Isso elimina a materialização intermediária do DataFrame e pode reduzir significativamente o uso de memória e o tempo de execução.
O modo de desempenho (compat_mode) e o mecanismo de execução (execution_engine) são eixos de configuração independentes:
| Config | Controla | Valores |
|---|
execution_engine | Qual mecanismo executa o processamento | auto, chdb, pandas |
compat_mode | Se a saída deve ser ajustada para compatibilidade com pandas | pandas, performance |
Definir compat_mode='performance' configura automaticamente execution_engine='chdb', já que o modo de desempenho foi projetado para execução de SQL.
from chdb.datastore.config import config
# Estes são independentes
config.use_chdb() # Força o engine chDB, mantém compatibilidade com pandas
config.use_performance_mode() # Força o engine chDB + remove sobrecarga do pandas
Ao escrever testes para o modo de desempenho, os resultados podem diferir do pandas na ordem das linhas e na estrutura do formato. Use estas estratégias:
Ordenar e comparar (agregações, filtros)
# Ordene ambos os lados pelas mesmas colunas antes de comparar
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)
Validação de faixa de valores (primeiro/último)
# first() com any() retorna um elemento arbitrário do grupo
result = ds.groupby("cat")["val"].first()
for group_key in groups:
assert result.loc[group_key] in group_values[group_key]
Esquema e contagem (LIMIT sem ORDER BY)
# head() sem sort_values: o conjunto de linhas é não determinístico
result = ds.head(5)
assert len(result) == 5
assert set(result.columns) == expected_columns
1. Habilite no início do script
from chdb.datastore.config import config
config.use_performance_mode()
# Todas as operações subsequentes se beneficiam
ds = pd.read_parquet("data.parquet")
result = ds[ds["amount"] > 100].groupby("region")["amount"].sum()
2. Adicione ordenação explícita quando a ordem for importante
# Para exibição ou processamento downstream que exige ordenação
result = (ds
.groupby("region")["revenue"].sum()
.sort_values(ascending=False)
)
3. Use em cargas de trabalho de batch/ETL
config.use_performance_mode()
# Pipeline ETL — a ordem não importa, o throughput sim
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. Alterne entre modos em uma sessão
# Modo de desempenho para computações pesadas
config.use_performance_mode()
aggregated = ds.groupby("cat")["val"].sum()
# De volta ao modo pandas para comparação de correspondência exata
config.use_pandas_compat()
detailed = ds[ds["val"] > 100].head(10)