Saltar al contenido principal
El método explain() muestra el plan de ejecución de una consulta de DataStore, lo que te ayuda a entender qué operaciones se realizarán y qué SQL se generará.

Uso básico

from pathlib import Path
Path("sales.csv").write_text("""\
region,product,category,amount,quantity,price,date,order_id
East,Widget,Electronics,5200,10,120,2024-01-15,1001
West,Gadget,Electronics,800,5,160,2024-02-20,1002
East,Gizmo,Home,6500,3,100,2024-03-10,1003
North,Widget,Electronics,4500,6,150,2024-06-18,1004
West,Gadget,Electronics,2000,8,250,2024-09-14,1005
""")

from chdb import datastore as pd

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

query = (ds
    .filter(ds['amount'] > 1000)
    .groupby('region')
    .agg({'amount': ['sum', 'mean']})
    .sort('sum', ascending=False)
)

# Ver el plan de ejecución
query.explain()

Sintaxis

explain(verbose=False) -> None
Parámetros:
ParámetroTipoPredeterminadoDescripción
verboseboolFalseMuestra metadatos adicionales

Formato de salida

Salida estándar

================================================================================
plan de ejecución (in execution order)
================================================================================

 [1] 📊 Data Source: file('sales.csv', 'csv')

Operations:
────────────────────────────────────────────────────────────────────────────────
    ️  Segment 1 [chDB] (from source): Operations 2-5
    ️  Note: SQL operations after Pandas ops use Python() table function

 [2] 🚀 [chDB] WHERE: "amount" > 1000
 [3] 🚀 [chDB] GROUP BY: region
 [4] 🚀 [chDB] AGGREGATE: sum(amount), avg(amount)
 [5] 🚀 [chDB] ORDER BY: sum DESC

────────────────────────────────────────────────────────────────────────────────
Final State: 📊 Pending (lazy, not yet executed)
             └─> Will execute when print(), .to_df(), .execute() is called

────────────────────────────────────────────────────────────────────────────────
Generated SQL Query:
────────────────────────────────────────────────────────────────────────────────

SELECT region, SUM(amount) AS sum, AVG(amount) AS mean
FROM file('sales.csv', 'csv')
WHERE "amount" > 1000
GROUP BY region
ORDER BY sum DESC

================================================================================

Leyenda de los iconos

IconoSignificado
📊Fuente de datos
🚀Operación de chDB (SQL)
🐼Operación de pandas

Salida detallada

query.explain(verbose=True)
El modo detallado muestra detalles adicionales de cada operación, incluida la consulta SQL completa con mecanismos internos de seguimiento del orden de las filas.

Tres fases de ejecución

La salida de EXPLAIN muestra las operaciones en tres fases:

Fase 1: Construcción de consultas SQL (diferida)

Operaciones que se compilan a SQL:
  1. Source: file('sales.csv', 'CSVWithNames')
  2. Filter: amount > 1000      
  3. GroupBy: region
  4. Aggregate: sum(amount)

Fase 2: Momento de ejecución

Cuando se produce un trigger:
  5. Execute SQL -> DataFrame
     Trigger: to_df() called

Fase 3: Operaciones de DataFrame

Operaciones posteriores a la ejecución:
  6. [pandas] pivot_table(...)
  7. [pandas] apply(custom_func)

Comprender el plan

Información de la fuente

Source: file('sales.csv', 'CSVWithNames')
  • file() - función de tabla file() de ClickHouse
  • 'CSVWithNames' - formato de archivo con fila de encabezado
Otros tipos de origen:
Source: s3('bucket/data.parquet', ...)
Source: mysql('host', 'db', 'table', ...)
Source: __dataframe__  (pandas DataFrame input)

Operaciones de filtrado

Filter: amount > 1000 AND status = 'active'
Muestra la cláusula WHERE que se aplicará.

GroupBy y Aggregate

GroupBy: region, category
Aggregate: sum(amount), avg(amount), count(id)
Muestra las columnas de GROUP BY y las funciones de agregación.

Operaciones de ordenación

Sort: sum DESC, region ASC
Muestra la cláusula ORDER BY.

Limitar operaciones

Limit: 10
Offset: 100
Muestra LIMIT y OFFSET.

Información del motor

Al usar el modo detallado, puede ver qué motor se utilizará:
Filter: amount > 1000
  - Engine: chdb
  - Pushdown: Yes

Apply: custom_function
  - Engine: pandas
  - Pushdown: No

Pushdown

  • : La operación se ejecutará en la fuente de datos (SQL)
  • No: La operación requiere ejecutarse con pandas

Ejemplos

Consulta simple

from pathlib import Path
Path("data.csv").write_text("""\
name,age,city,salary,department
Alice,25,NYC,55000,Engineering
Bob,30,LA,65000,Product
Charlie,35,NYC,80000,Engineering
Diana,28,SF,70000,Design
Eve,42,NYC,95000,Product
""")

ds = pd.read_csv("data.csv")
ds.filter(ds['age'] > 25).explain()
================================================================================
Plan de ejecución (en orden de ejecución)
================================================================================

 [1] 📊 Data Source: file('data.csv', 'csv')

Operaciones:
────────────────────────────────────────────────────────────────────────────────
    ️  Segment 1 [chDB] (desde la fuente): Operaciones 2-2

 [2] 🚀 [chDB] WHERE: "age" > 25

────────────────────────────────────────────────────────────────────────────────
Consulta SQL generada:
────────────────────────────────────────────────────────────────────────────────

SELECT * FROM file('data.csv', 'csv') WHERE "age" > 25

================================================================================

Agregación compleja

query = (ds
    .filter(ds['date'] >= '2024-01-01')
    .filter(ds['amount'] > 100)
    .select('region', 'category', 'amount')
    .groupby('region', 'category')
    .agg({
        'amount': ['sum', 'mean', 'count']
    })
    .sort('sum', ascending=False)
    .limit(20)
)
query.explain()
================================================================================
plan de ejecución (in execution order)
================================================================================

 [1] 📊 Data Source: file('sales.csv', 'csv')

Operations:
────────────────────────────────────────────────────────────────────────────────
    ️  Segment 1 [chDB] (from source): Operations 2-8

 [2] 🚀 [chDB] WHERE: "date" >= '2024-01-01'
 [3] 🚀 [chDB] WHERE: "amount" > 100
 [4] 🚀 [chDB] SELECT: region, category, amount
 [5] 🚀 [chDB] GROUP BY: region, category
 [6] 🚀 [chDB] AGGREGATE: sum(amount), avg(amount), count(amount)
 [7] 🚀 [chDB] ORDER BY: sum DESC
 [8] 🚀 [chDB] LIMIT: 20

────────────────────────────────────────────────────────────────────────────────
Generated SQL Query:
────────────────────────────────────────────────────────────────────────────────

SELECT region, category, 
       SUM(amount) AS sum, 
       AVG(amount) AS mean, 
       COUNT(amount) AS count
FROM file('sales.csv', 'csv')
WHERE "date" >= '2024-01-01' AND "amount" > 100
GROUP BY region, category
ORDER BY sum DESC
LIMIT 20

================================================================================

SQL y pandas combinados

Cuando las operaciones no pueden llevarse por completo a SQL, el plan muestra varios segmentos:
query = (ds
    .filter(ds['age'] > 25)           # SQL
    .groupby('city')                   # SQL
    .agg({'salary': 'mean'})           # SQL
    .apply(lambda x: x * 1.1)          # pandas (activa la división del segmento)
    .filter(ds['mean'] > 50000)        # SQL (nuevo segmento)
)
query.explain()
================================================================================
plan de ejecución (in execution order)
================================================================================

 [1] 📊 Data Source: file('data.csv', 'csv')

Operations:
────────────────────────────────────────────────────────────────────────────────
    ️  Segment 1 [chDB] (from source): Operations 2-4
    ️  Segment 2 [Pandas] (on DataFrame): Operation 5
    ️  Segment 3 [chDB] (on DataFrame): Operation 6
    ️  Note: SQL operations after Pandas ops use Python() table function

 [2] 🚀 [chDB] WHERE: "age" > 25
 [3] 🚀 [chDB] GROUP BY: city
 [4] 🚀 [chDB] AGGREGATE: avg(salary)
 [5] 🐼 [Pandas] APPLY: lambda
 [6] 🚀 [chDB] WHERE: "mean" > 50000

================================================================================

Depuración con explain()

Verificar la lógica de filtrado

# Verifica que tu filtro sea correcto
query = ds.filter((ds['age'] > 25) & (ds['city'] == 'NYC'))
query.explain()
# La salida muestra: Filter: age > 25 AND city = 'NYC'

Verificar la selección de columnas

# Comprobar la poda de columnas
query = ds.select('name', 'age').filter(ds['age'] > 25)
query.explain()
# La salida muestra: SELECT name, age FROM ... WHERE age > 25

Comprender la agregación

# Verificar funciones de agregación
query = ds.groupby('dept').agg({'salary': ['sum', 'mean', 'std']})
query.explain()
# La salida muestra: SELECT dept, SUM(salary), AVG(salary), stddevPop(salary)

Buenas prácticas

1. Verifique antes de ejecutar consultas grandes

# Siempre explicar primero para datos de gran volumen
query = ds.complex_pipeline()
query.explain()  # Verificar el plan

# Si el plan es correcto
result = query.to_df()  # Ejecutar

2. Usa detallado para depurar

# Cuando algo parece estar mal
query.explain(verbose=True)
# Muestra la selección del motor e información de pushdown

3. Comparar con to_sql()

# explain() muestra el plan
query.explain()

# to_sql() muestra solo el SQL
print(query.to_sql())

# Ambos útiles para distintos propósitos

4. Comprobar el estado del pushdown

# El modo detallado muestra si las operaciones se aplican con pushdown
query.explain(verbose=True)

# Si Pushdown: No, la operación se ejecuta en pandas
# Considere reestructurar la consulta para mejorar el rendimiento
Última modificación el 10 de junio de 2026