Pular para o conteúdo principal
O profiler do DataStore ajuda a medir o tempo de execução e identificar gargalos de desempenho.

Início rápido

from chdb import datastore as pd
from chdb.datastore.config import config, get_profiler

# Habilitar profiling
config.enable_profiling()

# Execute suas operações
ds = pd.read_csv("large_data.csv")
result = (ds
    .filter(ds['amount'] > 100)
    .groupby('category')
    .agg({'amount': 'sum'})
    .sort('sum', ascending=False)
    .head(10)
    .to_df()
)

# Visualizar relatório
profiler = get_profiler()
print(profiler.report())

Ativando o profiling

from chdb.datastore.config import config

# Habilitar profiling
config.enable_profiling()

# Desabilitar profiling
config.disable_profiling()

# Verificar se o profiling está habilitado
print(config.profiling_enabled)  # True ou False

API do Profiler

Como obter o Profiler

from chdb.datastore.config import get_profiler

profiler = get_profiler()

report()

Exibe um relatório de performance.
profiler.report(min_duration_ms=0.1)
Parâmetros:
ParâmetroTipoPadrãoDescrição
min_duration_msfloat0.1Mostra apenas passos com duração >= a este valor
Exemplo de saída:
======================================================================
EXECUTION PROFILE
======================================================================
   45.79ms (100.0%) Total Execution
     23.25ms ( 50.8%) Query Planning [ops_count=2]
     22.29ms ( 48.7%) SQL Segment 1 [ops=2]
       20.48ms ( 91.9%) SQL Execution
        1.74ms (  7.8%) Result to DataFrame
----------------------------------------------------------------------
      TOTAL:    45.79ms
======================================================================
O relatório mostra:
  • Duração em milissegundos para cada passo
  • Percentual do tempo em relação ao pai/total
  • Aninhamento hierárquico das operações
  • Metadados de cada passo (por exemplo, ops_count, ops)

step()

Meça manualmente o tempo de execução de um bloco de código.
with profiler.step("custom_operation"):
    # Seu código aqui
    expensive_operation()

clear()

Limpa todos os dados de profiling.
profiler.clear()

summary()

Retorna um dicionário que mapeia nomes de passos para durações (ms).
summary = profiler.summary()
for name, duration in summary.items():
    print(f"{name}: {duration:.2f}ms")
Exemplo de saída:
Total Execution: 45.79ms
Total Execution.Cache Check: 0.00ms
Total Execution.Query Planning: 23.25ms
Total Execution.SQL Segment 1: 22.29ms
Total Execution.SQL Segment 1.SQL Execution: 20.48ms
Total Execution.SQL Segment 1.Result to DataFrame: 1.74ms

Entendendo o relatório

Nomes dos passos

Nome do passoDescrição
Total ExecutionTempo total de execução
Query PlanningTempo gasto no planejamento da consulta
SQL Segment NExecução do segmento SQL N
SQL ExecutionExecução da consulta SQL
Result to DataFrameConversão dos resultados para pandas
Cache CheckVerificação do cache de consultas
Cache WriteGravação dos resultados no cache

Duração

  • Passos de planejamento (Planejamento da consulta): Geralmente rápidas
  • Passos de execução (Execução SQL): Onde o trabalho de fato acontece
  • Passos de transferência (Resultado para DataFrame): Conversão dos dados para pandas

Identificação de gargalos

======================================================================
EXECUTION PROFILE
======================================================================
  200.50ms (100.0%) Total Execution
    10.25ms (  5.1%) Query Planning [ops_count=4]
   190.00ms ( 94.8%) SQL Segment 1 [ops=4]
     185.00ms ( 97.4%) SQL Execution    <- Main bottleneck
       5.00ms (  2.6%) Result to DataFrame
----------------------------------------------------------------------
      TOTAL:   200.50ms
======================================================================

Padrões de profiling

Gerar o perfil de uma única consulta

config.enable_profiling()
profiler = get_profiler()
profiler.clear()  # Limpar dados anteriores

# Executar consulta
result = ds.filter(...).groupby(...).agg(...).to_df()

# Visualizar o perfil desta consulta
print(profiler.report())

Analisar o perfil de várias consultas

config.enable_profiling()
profiler = get_profiler()
profiler.clear()

# Consulta 1
with profiler.step("Query 1"):
    result1 = query1.to_df()

# Consulta 2
with profiler.step("Query 2"):
    result2 = query2.to_df()

print(profiler.report())

Compare as abordagens

profiler = get_profiler()

# Abordagem 1: Filtrar e depois agrupar
profiler.clear()
with profiler.step("filter_then_groupby"):
    result1 = ds.filter(ds['x'] > 10).groupby('y').sum().to_df()
summary1 = profiler.summary()
time1 = summary1.get('filter_then_groupby', 0)

# Abordagem 2: Agrupar e depois filtrar
profiler.clear()
with profiler.step("groupby_then_filter"):
    result2 = ds.groupby('y').sum().filter(ds['x'] > 10).to_df()
summary2 = profiler.summary()
time2 = summary2.get('groupby_then_filter', 0)

print(f"Approach 1: {time1:.2f}ms")
print(f"Approach 2: {time2:.2f}ms")
print(f"Winner: {'Approach 1' if time1 < time2 else 'Approach 2'}")

Dicas de otimização

1. Verifique o tempo de execução do SQL

Se SQL execution for o gargalo:
  • Adicione mais filtros para reduzir o volume de dados
  • Use Parquet em vez de CSV
  • Verifique se os índices estão adequados (para fontes de banco de dados)

2. Verifique o tempo de E/S

Se read_csv ou read_parquet for o gargalo:
  • Use Parquet (colunar, comprimido)
  • Leia apenas as colunas necessárias
  • Faça o filtro na origem, se possível

3. Verifique a transferência de dados

Se to_df estiver lento:
  • O conjunto de resultados pode estar grande demais
  • Adicione mais filtros ou um limite
  • Use head() para visualizar uma amostra

4. Compare os motores

from chdb.datastore.config import config

# Profiling com chdb
config.use_chdb()
profiler.clear()
result_chdb = query.to_df()
time_chdb = profiler.total_duration_ms

# Profiling com pandas
config.use_pandas()
profiler.clear()
result_pandas = query.to_df()
time_pandas = profiler.total_duration_ms

print(f"chdb: {time_chdb:.2f}ms")
print(f"pandas: {time_pandas:.2f}ms")

Boas práticas

1. Faça o perfil antes de otimizar

# Não adivinhe - meça!
config.enable_profiling()
result = your_query.to_df()
print(get_profiler().report())

2. Limpe entre os testes

profiler.clear()  # Limpar dados anteriores
# Executar teste
print(profiler.report())

3. Use min_duration_ms para focar

# Mostrar apenas operações >= 100ms
profiler.report(min_duration_ms=100)

4. Faça o perfil com dados representativos

# Faça o perfil com tamanhos de dados reais
# Dados de teste pequenos podem não revelar os gargalos reais

5. Desative em produção

# Development
config.enable_profiling()

# Production
config.set_profiling_enabled(False)  # Evitar sobrecarga

Exemplo: Sessão completa de profiling

from chdb import datastore as pd
from chdb.datastore.config import config, get_profiler

# Setup
config.enable_profiling()
config.enable_debug()  # Veja também o que está acontecendo
profiler = get_profiler()

# Carregar dados
profiler.clear()
print("=== Loading Data ===")
ds = pd.read_csv("sales_2024.csv")  # 10M linhas
print(profiler.report())

# Consulta 1: Filtro simples
profiler.clear()
print("\n=== Query 1: Simple Filter ===")
result1 = ds.filter(ds['amount'] > 1000).to_df()
print(profiler.report())

# Consulta 2: Agregação complexa
profiler.clear()
print("\n=== Query 2: Complex Aggregation ===")
result2 = (ds
    .filter(ds['amount'] > 100)
    .groupby('region', 'category')
    .agg({
        'amount': ['sum', 'mean', 'count'],
        'quantity': 'sum'
    })
    .sort('sum', ascending=False)
    .head(20)
    .to_df()
)
print(profiler.report())

# Resumo
print("\n=== Summary ===")
print(f"Query 1: {len(result1)} rows")
print(f"Query 2: {len(result2)} rows")
Última modificação em 10 de junho de 2026