Files
fn_registry/python/functions/pipelines/profile_database.md
T
egutierrez 763e06c127 feat(browser): auto-commit con 178 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-20 18:22:23 +02:00

5.6 KiB

name, kind, lang, domain, purity, version, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, params, output
name kind lang domain purity version signature description tags uses_functions uses_types returns returns_optional error_type imports tested tests test_file_path file_path params output
profile_database pipeline py pipelines impure 1.0.0 def profile_database(db_path: str, tables: list = None, sample: int = 5000, report_dir: str = "reports", write_report: bool = True, min_inclusion: float = 0.9) -> dict Orquestador one-shot del grupo eda a nivel de BASE: perfila TODA una base DuckDB (todas las tablas o las indicadas) componiendo profile_table por tabla, infiere las relaciones FK inter-tabla por containment y construye el join graph con diagrama Mermaid. Ensambla un DatabaseProfile (resumen por tabla + TableProfiles completos + fk_candidates + join_graph) y opcionalmente emite un report markdown DB-level + JSON sidecar. Es la composicion canonica para hazme un EDA de esta base de datos y entender su esquema relacional.
eda
relations
duckdb
profiling
data-quality
pipeline
dataops
profile_table_py_pipelines
infer_fk_containment_duckdb_py_datascience
build_join_graph_py_datascience
duckdb_list_tables_py_infra
render_eda_markdown_py_datascience
false error_go_core
true
profile_database_two_related_tables
profile_database_writes_report
python/functions/pipelines/profile_database_test.py python/functions/pipelines/profile_database.py
name desc
db_path Ruta al archivo DuckDB (read-only, debe existir; no se crea).
name desc
tables Lista de tablas a perfilar. None (default) usa todas las del esquema main via duckdb_list_tables.
name desc
sample Maximo de valores no nulos muestreados por columna en el perfil de cada tabla (se pasa a profile_table). Default 5000.
name desc
report_dir Directorio donde escribir los reports DB-level si write_report. Default 'reports'. Se crea si no existe.
name desc
write_report Si True (default) escribe report markdown DB-level + JSON sidecar timestamped en report_dir; si False no toca disco y los paths del retorno son None.
name desc
min_inclusion Umbral minimo de inclusion (0-1) para emitir una FK candidata (se pasa a infer_fk_containment_duckdb). Default 0.9.
dict {status:'ok', db_profile:<DatabaseProfile con db_path, profiled_at, n_tables, tables[resumen], table_profiles[completos], fk_candidates, join_graph{nodes,edges,mermaid,hubs}, errors>, report_md_path:str|None, report_json_path:str|None} o {status:'error', error:str} (dict-no-throw).

Ejemplo

import os
import tempfile
import duckdb
from pipelines.profile_database import profile_database

# Base DuckDB de juguete en /tmp: customers <- orders (relacionadas).
db = os.path.join(tempfile.mkdtemp(), "shop.duckdb")
con = duckdb.connect(db)
con.execute("CREATE TABLE customers (id INTEGER, name VARCHAR, city VARCHAR)")
con.execute("INSERT INTO customers VALUES (1,'Ana','Madrid'),(2,'Luis','Sevilla'),(3,'Marta','Bilbao')")
con.execute("CREATE TABLE orders (order_id INTEGER, customer_id INTEGER, total DOUBLE)")
con.execute("INSERT INTO orders VALUES (10,1,99.5),(11,1,12.0),(12,2,45.0),(13,3,7.25)")
con.close()

r = profile_database(db, write_report=False)
print(r["status"], r["db_profile"]["n_tables"])           # ok 2
print([fk["from_table"]+"."+fk["from_col"]+"->"+fk["to_table"]+"."+fk["to_col"]
       for fk in r["db_profile"]["fk_candidates"]])
# ['orders.customer_id->customers.id']  -> FK inferida por containment
print(r["db_profile"]["join_graph"]["mermaid"].splitlines()[0])  # graph LR

# Con report DB-level a disco (markdown con diagrama Mermaid + JSON sidecar):
r = profile_database(db, report_dir="reports")
print(r["report_md_path"], r["report_json_path"])
# reports/eda_db_20260620-101500.md reports/eda_db_20260620-101500.json

Cuando usarla

Cuando necesites entender una BASE de datos entera de un golpe: el perfil de todas sus tablas mas su esquema relacional (que tabla referencia a cual, con que cardinalidad) en una sola llamada. Usala al recibir una base DuckDB desconocida, para documentar un data warehouse, para descubrir el star schema (las tablas hub del join graph) o antes de escribir joins sin tener el modelo declarado. Es el escalon DB-level sobre profile_table (que perfila una sola tabla): aqui ademas se infieren las FK y se dibuja el diagrama de relaciones.

Gotchas

  • Impura: con write_report=True (default) ESCRIBE dos archivos a report_dir (markdown DB-level + JSON sidecar). Pasa write_report=False para un dry-run sin tocar disco.
  • Las FK se infieren por CONTAINMENT, es una HEURISTICA: A->B es candidata si los valores distintos de A estan contenidos en B (>= min_inclusion) y B parece clave (alta unicidad en su tabla). Puede dar falsos positivos (columnas que comparten dominio sin ser FK real, p.ej. dos columnas de codigos de pais) o perder FK reales si min_inclusion es muy alto o los datos estan sucios. Es un punto de partida para mapear el esquema, no un DDL autoritativo.
  • Perfila TODAS las tablas por defecto: en bases grandes (muchas tablas o tablas muy anchas) puede TARDAR. Acota con tables=[...] o baja sample. La inferencia de FK ademas salta pares hacia tablas con mas de 200k filas (lado caro del INTERSECT); esas relaciones quedan sin evaluar.
  • Tolera fallos por tabla: si el perfil de una tabla concreta falla, se anota en db_profile["errors"] y se sigue con las demas; n_tables cuenta solo las perfiladas con exito. Revisa errors para saber que quedo fuera.
  • db_path debe existir: DuckDB read-only NO crea la base. El muestreo de cada tabla usa el sandbox read-only por defecto (sin acceso a FS/red).