Procesamiento Incremental: Actualizaciones Rápidas del Pipeline
Este artículo explica cómo el pipeline de SEO utiliza el procesamiento incremental para ejecutarse en segundos en lugar de horas.
El Problema: El Reprocesamiento Completo es Lento
Ejecutar todo el pipeline desde cero toma horas:
-
Paso 0 (Inserción de fuentes): 15 minutos (65,000 productos)
-
Paso 1 (Obtención de consultas): 10 minutos (llamadas API)
-
Paso 2 (Agrupación de consultas): 30 minutos (similitud 65K×65K)
-
Paso 3 (Mapeos de frases): 20 minutos (inserción + coincidencia)
-
Paso 4 (Coincidencia de productos): 45 minutos (consultas × productos)
-
Paso 5 (Búsquedas relacionadas): 25 minutos (similitud consulta × consulta)
Total: ~2.5 horas para el pipeline completo
Problema: Las actualizaciones diarias desperdiciarían 2.5 horas recalculando datos inalterados.
La Solución: Estrategia Incremental de Tres Capas
Utilizamos tres técnicas para omitir trabajo innecesario:
1. Omisión de Pasos (Granularidad Gruesa)
Omitir pasos completos si la salida está actualizada y el script no ha cambiado.
2. Inserción Incremental (Granularidad Media)
Insertar solo elementos nuevos/cambiados, reutilizar inserciones en caché.
3. Puntos de Control (Granularidad Fina)
Guardar el progreso durante operaciones largas, reanudar desde el punto de control en caso de fallo.
Estrategia de Omisión de Pasos
Cómo Funciona
Antes de cada paso, verificar:
¿Existe la salida? Si no, ejecutar el paso.
Antigüedad de la salida: Si es mayor a 7 días, ejecutar el paso.
¿Cambió el script? Si el script se modificó desde que se generó la salida, ejecutar el paso.
¿Pasaron todas las verificaciones? Omitir el paso.
Implementación
def should_skip_step(output_path, script_path, days=7):
# Verificar si la salida existe
if not os.path.exists(output_path):
# ... (detalles de implementación omitidos)
Uso
Cada script verifica al inicio:
from seo_common import should_skip_step
if should_skip_step(SEO_SOURCE_EMBEDDINGS_PATH, __file__):
print("✓ Omitiendo: La salida está actualizada y el script no ha cambiado")
return
Beneficios
Ejecuciones diarias rápidas: La mayoría de los pasos se omiten si los datos no cambian
Invalidación automática: Los cambios en el script activan una re-ejecución
Actualización configurable: Ajustar el parámetro days por paso
Estrategia de Inserción Incremental
Cómo Funciona
Al insertar elementos (productos, consultas, frases):
Cargar caché: Leer elementos previamente insertados y sus claves
Comparar claves: Identificar elementos nuevos, cambiados y eliminados
Insertar solo lo nuevo: Insertar solo elementos que no están en la caché
Combinar: Combinar inserciones en caché con nuevas inserciones en el orden correcto
Guardar: Escribir la caché actualizada
Implementación
La función incremental_embed_with_keys maneja esto:
def incremental_embed_with_keys(
items, # Elementos actuales a insertar
keys, # Claves únicas para los elementos
# ... (detalles de implementación omitidos)
Tasas de Acierto de la Caché
Tasas de acierto típicas después de la primera ejecución:
Datos fuente (productos, partes, artículos):
-
Primera ejecución: 0% (insertar todos los 65,000 elementos)
-
Ejecución diaria: 99.5% (solo ~300 elementos nuevos/cambiados)
Consultas (de GSC, Ads, en vivo):
-
Primera ejecución: 0% (insertar todas las 65,000 consultas)
-
Ejecución diaria: 99.2% (solo ~500 consultas nuevas)
Mapeos de frases:
-
Primera ejecución: 0% (insertar todas las 5,000 frases)
-
Ejecución diaria: 99.8% (solo ~10 frases nuevas)
Impacto en el Rendimiento
Primera ejecución (caché fría):
-
Inserción de fuentes: 15 minutos (65,000 elementos)
-
Inserción de consultas: 10 minutos (65,000 consultas)
-
Inserción de frases: 2 minutos (5,000 frases)
Ejecución diaria (caché caliente):
-
Inserción de fuentes: 10 segundos (300 elementos, tasa de acierto 99.5%)
-
Inserción de consultas: 5 segundos (500 consultas, tasa de acierto 99.2%)
-
Inserción de frases: 1 segundo (10 frases, tasa de acierto 99.8%)
Aceleración: 90-180× más rápido
Estrategia de Puntos de Control
Cómo Funciona
Para operaciones de larga duración (insertar 65,000 elementos):
Procesamiento por lotes: Procesar elementos en lotes (ej., 1,000 elementos)
Guardar punto de control: Después de cada lote, guardar los resultados acumulados
Reanudar en caso de fallo: Si el proceso falla, reanudar desde el último punto de control
Guardado final: Después de todos los lotes, guardar los resultados completos
Implementación
Los puntos de control están integrados en incremental_embed_with_keys:
checkpoint_every = 1000 # Guardar cada 1,000 elementos
embeddings_list = []
# ... (detalles de implementación omitidos)
Beneficios
Recuperación ante fallos: Reanudar desde el último punto de control en lugar de comenzar de nuevo
Visibilidad del progreso: Ver el progreso cada 1,000 elementos
Eficiencia de memoria: Procesar por lotes, no cargar todo a la vez
Integración en Todo el Pipeline
El procesamiento incremental se utiliza en múltiples pasos:
Paso 0: Inserción de Datos Fuente
Incremental: Insertar solo productos, partes, artículos nuevos/cambiados
Puntos de control: Guardar cada 1,000 elementos
Lógica de omisión: Omitir si la salida tiene < 7 días y el script no ha cambiado
Ver: Inserción de Datos Fuente
Paso 1: Obtención de Consultas
Incremental: Las llamadas API obtienen solo datos nuevos (desde la última ejecución)
Lógica de omisión: Omitir si la salida tiene < 1 día
Paso 3b: Inserción de Consultas
Incremental: Insertar solo consultas nuevas
Puntos de control: Guardar cada 1,000 consultas
Lógica de omisión: Omitir si la salida tiene < 7 días y el script no ha cambiado
Paso 4: Expansión de Mapeo de Frases
Incremental: Insertar solo frases nuevas
Puntos de control: Guardar cada 1,000 frases
Lógica de omisión: Omitir si la salida tiene < 7 días y el script no ha cambiado
Paso 6: Coincidencia de Productos
Incremental: Coincidir solo consultas nuevas
Lógica de omisión: Omitir si la salida tiene < 7 días y el script no ha cambiado
Ver: Coincidencia de Productos
Configuración
El procesamiento incremental se configura por paso:
Umbral de Actualización
# Omitir si la salida tiene < 7 días (predeterminado)
should_skip_step(output_path, script_path, days=7)
# Omitir si la salida tiene < 1 día (para datos que cambian con frecuencia)
should_skip_step(output_path, script_path, days=1)
Frecuencia de Puntos de Control
# Guardar cada 1,000 elementos (predeterminado)
incremental_embed_with_keys(..., checkpoint_every=1000)
# Guardar cada 5,000 elementos (para procesamiento más rápido, menos seguridad)
incremental_embed_with_keys(..., checkpoint_every=5000)
Tamaño del Lote
# Insertar 32 elementos por lote (predeterminado, equilibrado)
incremental_embed_with_keys(..., batch_size=32)
# Insertar 64 elementos por lote (más rápido en GPU, más memoria)
incremental_embed_with_keys(..., batch_size=64)
Monitoreo y Depuración
Estadísticas de la Caché
Cada paso imprime estadísticas de la caché:
✓ Caché existente encontrada, verificando cambios...
Existente: 65,000 elementos
Actual: 65,300 elementos
Reutilizando: 64,800 inserciones
Nuevo: 500 elementos a insertar
Mensajes de Omisión
Cuando se omiten pasos:
✓ Omitiendo 0_embed_source_data.py: La salida está actualizada y el script no ha cambiado.
Mensajes de Puntos de Control
Durante operaciones largas:
Insertando 65,000 elementos (puntos de control cada 1,000)...
Lote 0-1000...
✓ Punto de control guardado (1,000 total)
Lote 1000-2000...
✓ Punto de control guardado (2,000 total)
...
Referencias
Conceptos Técnicos
-
Aprendizaje Incremental - Wikipedia
-
Puntos de Control - Wikipedia
-
Caché - Wikipedia
Artículos Relacionados
-
Descripción General del Pipeline de SEO - Arquitectura completa del pipeline
-
Inserción de Datos Fuente - Inserción incremental de productos
-
Inserción de Consultas - Inserción incremental de consultas
-
Mapeos de Frase a Filtro - Inserción incremental de frases
Resumen
El procesamiento incremental hace que el pipeline sea 90-180× más rápido:
Estrategia de tres capas:
-
✅ Omisión de pasos (omitir pasos completos si la salida está actualizada)
-
✅ Inserción incremental (insertar solo elementos nuevos/cambiados)
-
✅ Puntos de control (guardar progreso, reanudar en caso de fallo)
Rendimiento:
-
✅ Primera ejecución: ~2.5 horas (pipeline completo)
-
✅ Ejecución diaria: ~5 minutos (actualizaciones incrementales)
-
✅ Tasas de acierto de caché: 99%+ después de la primera ejecución
Beneficios:
-
✅ Actualizaciones diarias rápidas (minutos en lugar de horas)
-
✅ Invalidación automática (los cambios en el script activan re-ejecución)
-
✅ Recuperación ante fallos (reanudar desde punto de control)
-
✅ Eficiente en memoria (procesamiento por lotes)
Esta estrategia permite ejecuciones diarias del pipeline sin desperdiciar capacidad de cálculo en datos inalterados.