Optimización base de datos SolerApp
Soler

Soporte técnico · Mantenimiento evolutivo

Optimización de rendimiento de la base de datos de SolerApp

Registro del diagnóstico, los scripts ejecutados en producción, el motivo de cada uno, el resultado esperado y el resultado obtenido.

Transversa ITTransversa IT

Cliente: Soler, Centro de Bienestar y Salud Proveedor: Transversa IT Base de datos: bigboss (MySQL 8.0.18) Ejecución: 2026-10-17 01:09 a 02:23 (hora Colombia) Fuente: Documento generado por Transversa IT a partir de los registros de MySQL y del análisis de los repositorios Soler-AppWin y Soler-AppWeb. Última actualización: 2026-10-18 22:54 Generado por: Ing. Mauricio Páramo Calle · soluciones@transversa-it.com

Resumen

Resumen

Objetivo del análisis

El objetivo planteado fue analizar la base de datos porque el sistema se percibe lento y los servidores son costosos, con la idea de evaluar una migración a PostgreSQL. Antes de decidir una migración se midió dónde está realmente el cuello de botella, para no pagar un cambio de motor que no resuelva el problema.

La base de datos de Soler casi no tenía índices secundarios: unos 7 GB de datos contra 0,08 MB de índices. Las consultas más frecuentes de las aplicaciones recorrían tablas completas en cada ejecución. Tres consultas concentraban el 95,8 % del tiempo de base de datos del periodo medido.

Cifras obtenidas de la estructura exportada el 2026-10-16.

ElementoValor
Tablas270
Columnas4.441
Llaves foráneas declaradas2
Tablas sin llave primaria40
Tablas sin ningún índice40
Tablas de registro (_log)32
Tamaño de datos≈ 7,05 GB
Tamaño de índices secundarios≈ 0,08 MB
Motores de almacenamientoInnoDB 252 · MyISAM 18
Tablas con más de 10.000 filas y solo la llave primaria (o ninguna)34

En la madrugada del 2026-10-17 se crearon dos índices en producción, sin bloquear las tablas y con un respaldo previo. Las dos consultas principales dejaron de recorrer la tabla completa optimizando los recursos del servidor y mejorando los tiempos de respuesta.

164.400 → 1
filas leídas por la consulta de tareas por sede (bbf_tasks)
377.576 → 53.278
filas leídas por la cola de impresión de facturas (bbf_facturas), 7 veces menos
2 índices creados
optimiza recursos en servidor y mejora tiempos de respuesta
Ver más →
0
filas de datos modificadas; no se cambió ningún dato

Reparto del tiempo total de consultas

Cargando mediciones…

Antes, tres consultas ocupaban el 95,8 % del tiempo del servidor. Después de los índices, esas tres bajan a cerca del 51 % y el resto del trabajo del servidor pasa a ser casi la mitad. Son porcentajes de cada periodo medido, no tiempos absolutos. La cola de impresión sigue siendo la consulta que más pesa.

Cargando…
Qué significa que los porcentajes suban o bajen

Cada porcentaje es la parte del tiempo total de consultas que ocupa una consulta en ese periodo. Es una proporción, no un tiempo: por eso se lee junto con los segundos por ejecución y las consultas simultáneas.

  • Baja el porcentaje de una consulta pesada: esa consulta dejó de dominar el servidor, porque se volvió más rápida o porque se ejecuta menos. Es el efecto buscado con los índices.
  • Sube el porcentaje de una consulta: pasó a ser el principal cuello de botella y es la candidata para la siguiente optimización. También puede subir porque el resto del trabajo bajó, aunque ella no haya empeorado.
  • Sube el porcentaje de «Todas las demás consultas»: el trabajo se repartió mejor entre muchas consultas y ya no hay tres que concentren el tiempo del servidor.

Un porcentaje alto no significa que el servidor esté lento, ni uno bajo que esté rápido: lo que confirma la mejora es que los segundos por ejecución y las consultas simultáneas bajen.

Indicadores clave de la mejora

Antes frente a la última medición. Flecha verde: bajó y eso es positivo. Flecha roja: subió y eso es negativo.
Cargando…

Detalle completo y evolución en cada revisión: sección Resultados medidos.

Qué falta para cerrar la mejora

El efecto sobre el plan de ejecución ya está comprobado. El efecto sobre el tiempo total de base de datos se comprobará con la misma medición de línea base dentro de 24 a 48 horas (sección Pendiente de validar). Un cambio pequeño en el código de las aplicaciones permitirá reducir aún más la lectura de bbf_facturas.

Hallazgo adicional del 2026-10-17

La tabla maquinaslog no recibe datos desde 2024-04-01 y su contador de identificadores está en el límite máximo de su tipo.

Contexto

Soler opera una cadena de centros de bienestar y salud con cámaras de terapia para la piel. Su sistema se compone de una aplicación Windows (Visual Basic .NET, Windows Forms), una aplicación web (ASP.NET, VB.NET) y una base de datos MySQL llamada bigboss.

El objetivo planteado fue analizar la base de datos porque el sistema se percibe lento y los servidores son costosos, con la idea de evaluar una migración a PostgreSQL. Antes de decidir una migración se midió dónde está realmente el cuello de botella, para no pagar un cambio de motor que no resuelva el problema.

Cómo se hizo el análisis

  • Lectura de la estructura de la base de datos (tablas, columnas, índices, motores) desde MySQL Workbench, en solo lectura.
  • Lectura de las estadísticas de consultas del servidor (performance_schema), que registran qué consultas consumen más tiempo.
  • Revisión del código fuente de las aplicaciones Windows y Web para ubicar el origen de las consultas más pesadas.
  • Verificación con EXPLAIN, que muestra cómo MySQL planea ejecutar una consulta sin ejecutarla.

Costos del proyecto

$2.670.000
total del proyecto, fases 1 a 7
$480.000
fase 1, ya realizada
$2.190.000
fases 2 a 5, por ejecutar
$0
seguimiento y seguridad de datos
Fase 1: ejecución inicial, realizada hasta el 2026-10-17 · $480.000

Transversa-IT la realizó por iniciativa propia, sin aprobación previa del cliente, con el fin de mejorar y optimizar el servidor y la experiencia de los usuarios. Consistió en el análisis de la base de datos para optimizar las consultas en el servidor y mejorar el rendimiento del aplicativo.

FaseQué incluyeValor (COP)
1. Ejecución inicial
Realizada
Diagnóstico de la base de datos (270 tablas) y de las consultas que más pesan; plan con salvaguardas y reversa; verificaciones previas; creación de dos índices sin bloquear tablas; cancelación de cinco consultas atascadas; verificación con EXPLAIN; mediciones 1 y 2 del servidor; documento de soporte.$480.000
2. Correcciones sobre los hallazgos de la base de datosCorrecciones para optimizar la base de datos sobre los hallazgos identificados, incluido el segundo lote de índices propuesto para bbf_maquinas_log y bbf_facturas, con verificación de respaldo, creación en línea, comprobación y reversa documentada.$460.000
3. Corrección de consultas atascadasLímite de palabras y de tiempo en la búsqueda de personas; ajuste de optimizer_search_depth con pruebas; reescritura del procedimiento find_Person; script de vigilancia.$750.000
4. Consultas de facturaciónCambio de DATE_FORMAT por rangos de fecha en la cola de impresión, ventas del día y cierres, y cambio de TRIM en la consulta de pagos, con pruebas y despliegue coordinado.$450.000
5. Retención de registrosPolítica de retención y archivo de maquinaslog y er_facturacion_electronica_log, y revisión del corte de datos de maquinaslog desde 2024-04-01.$530.000
6. Seguimiento de las mejorasSeguimiento de las mejoras en la base de datos y de los cambios necesarios en la aplicación durante el proyecto: mediciones de validación con el mismo método, comparación con "antes" y actualización de este documento.$0
7. Seguridad de datosRetiro de la credencial escrita en el código y cambio de la contraseña, y revisión de otras credenciales en los repositorios. Tiempo estimado: 1 hora, sin costo.$0
Total del proyecto$2.670.000
Fuera del proyecto: evaluación de PostgreSQL

La migración a PostgreSQL no hace parte de este proyecto. Transversa-IT hará por su cuenta la evaluación, después de las mejoras en la base de datos, para proponerle a Soler más adelante un cambio de tecnología, tanto de la base de datos como de la aplicación, que reduzca los costos mensuales del servidor y mejore la experiencia de los usuarios.

Condiciones comerciales

  1. Forma de pago: la fase 1 ya está realizada. Para las fases 2 a 5, 50 % del valor de cada fase al aprobarla, como anticipo, y 50 % al publicarla en producción o entregarla.
  2. Respaldo y restauración: el respaldo de la información y de la base de datos se realiza de forma automática a través de Acronis. Cada operación sobre la base de datos se hará en horario no laboral, después de las 9 p. m. hora Colombia, y Transversa-IT hará antes la copia de la base de datos.
    En caso de requerir restaurar la base de datos en producción, se informará el incidente con antelación, se detendrá la ejecución de la aplicación para evitar que se modifique información, y Transversa-IT hará la recuperación de la base de datos y volverá a habilitar la aplicación.
  3. Los valores no incluyen: soporte sobre el servidor, reinstalación del aplicativo, recuperación de datos, respaldo de información del sistema, respaldo de información de la base de datos, requerimientos adicionales, manual de usuario, capacitaciones a usuario final, instalaciones sobre los servidores y dispositivos, ni soporte a usuario final.
  4. Fuera del alcance definido: está por fuera cualquier análisis y ejecución de migraciones del aplicativo y la base de datos.
  5. Requerimientos adicionales: los que estén fuera del alcance definido podrán generar horas adicionales, que se avisan y se aprueban antes de continuar.
  6. Código fuente y documentación: los valores en pesos colombianos de este documento incluyen el código fuente de las aplicaciones y la documentación técnica generada durante la ejecución del proyecto, junto con los scripts de medición.
  7. Soporte y garantía: garantía sobre las funcionalidades y modificaciones realizadas durante el periodo en que el proyecto esté en ejecución y un mes después de finalizado.
  8. Desplazamiento, estadía y alimentación derivados de cualquier actividad por fuera de Medellín y el Área Metropolitana corren por cuenta del cliente, además de los servicios adicionales a los especificados en esta propuesta.

Consultas que más pesan

Ventana medida: de 2026-10-14 07:47 a 2026-10-16 12:32 (unas 52,7 horas). Se acumularon 507.244 segundos de trabajo de base de datos, es decir, en promedio unas 2,7 consultas ejecutándose todo el tiempo. De 2,40 millones de ejecuciones del top 100, 1,38 millones no usaron ningún índice.

#Qué haceEjecucionesTiempo total% del top 100
1Cola de impresión de facturas pendientes (la app Windows la consulta cada pocos segundos)1.042.326418.543 s82,5 %
2Variante de la anterior, con filtro adicional por fecha105.48943.669 s8,6 %
3Tareas pendientes por sede99.99723.683 s4,7 %

Estas tres consultas suman el 95,8 % del tiempo medido. La consulta 1 examinó en promedio unas 483.000 filas por ejecución para devolver, en total, solo 237 filas durante toda la ventana: casi siempre la respuesta era "no hay nada pendiente", pero se leía toda la tabla para saberlo.

Causas verificadas en el código y con EXPLAIN

  • bbf_facturas solo tenía la llave primaria (ID_FACTURA, ID_SEDE). Filtrar por sede no puede usar ese índice, porque la sede es la segunda columna, y MySQL leía las ~378 mil filas.
  • La condición DATE_FORMAT(IMPRESO, …) = '1900/01/01' aplica una función a la columna y evita que un índice sobre IMPRESO se aproveche por completo.
  • bbf_tasks solo tenía la llave primaria (intId), sin índice por sede ni por estado.

Línea base con EXPLAIN (2026-10-16 12:47, producción, solo lectura)

ConsultaTablaTipo de accesoÍndice usadoFilas estimadas
Cola de impresiónbbf_facturasALL (tabla completa)ninguno377.576
Tareas pendientesbbf_tasksALL (tabla completa)ninguno164.400

Hallazgos iniciales

Implicación para la decisión de migrar

Como el problema principal es la falta de índices y no el motor, conviene medir el efecto de los índices en MySQL antes de migrar. Si la mejora es grande, la migración deja de justificarse por rendimiento y pasa a justificarse sobre todo por costo de servidores.

Hallazgos principales

  1. Falta casi total de índices secundarios. Los filtros y cruces por persona, sede, factura o fecha recorren la tabla completa. Es la causa más probable de la lentitud y no depende del motor de base de datos.
  2. Integridad referencial casi inexistente. Solo 2 llaves foráneas declaradas. Las relaciones entre tablas viven en el código de las aplicaciones.
  3. 40 tablas sin llave primaria y 5 con llave primaria de tipo decimal (bbf_acceso, bbf_personas, bbf_productos, er_facturacion_electronica_log, maquinaslog).
  4. Tipos inconsistentes para la misma clave. Por ejemplo, ID_PERSONA aparece como texto, decimal y entero según la tabla.
  5. Dos tablas de registro concentran cerca del 84 % del volumen: maquinaslog (≈ 15,4 millones de filas) y er_facturacion_electronica_log (≈ 7,0 millones de filas, ≈ 5,1 GB).
  6. 18 tablas en MyISAM, un motor sin transacciones ni integridad.
  7. Codificación de caracteres mezclada (latin1, utf8 y utf8mb4), un riesgo para tildes y eñes en una futura migración.
  8. Documentación casi nula en el esquema: 25 de 4.441 columnas tienen comentario.

Fase 1. Ejecución inicial

En esta fase Transversa-IT revisó la base de datos de Soler, creó dos índices para que las consultas más pesadas dejaran de recorrer tablas completas y canceló cinco consultas que llevaban horas abiertas. No se modificó ningún dato. Es un resumen de lo ejecutado; el detalle de cada paso, con sus scripts, está en la sección siguiente.

En palabras simples

Un índice funciona como el índice de contenido de un libro: en lugar de leer todas las páginas para encontrar un tema, MySQL va directo a las filas que necesita, por sede o por estado.

Qué se hizo

CuándoQué se hizoTécnicamente
2026-10-14 a 10-16Se revisó la estructura de la base y se midió qué consultas consumían más tiempo del servidor.Estructura exportada (270 tablas), estadísticas de performance_schema y planes EXPLAIN. Scripts y documentos: 00_diagnostico_bigboss.md, 01_analisis_queries.md.
2026-10-16Se propusieron dos índices y se preparó la ejecución con sus salvaguardas.propuesta_indices_mysql.sql, ejecucion_indices_produccion.sql (con los comandos de cambio comentados a propósito) y runbook_indices_9pm.md.
2026-10-17 01:09 a 02:08Transversa-IT hizo una copia completa de la base de datos antes de tocar nada.Base bigboss del servidor 200.118.190.188. Archivo E:\itBigBoss\Transversa-IT\BigbossBackup 20261017 0117.zip.
2026-10-17 02:09 a 02:11Se verificó que el servidor estaba tranquilo y sin trabajos largos antes de empezar.Consultas de solo lectura sobre innodb_trx, processlist y variables de espera.
2026-10-17 02:13Se creó el primer índice (tareas por sede) en 2,6 segundos.ALTER TABLE bbf_tasks ADD INDEX …, ALGORITHM=INPLACE, LOCK=NONE.
2026-10-17 02:14Se cancelaron tres consultas que llevaban unas 10 horas abiertas.KILL QUERY 855; 857; 934;. Detalle en Consultas atascadas.
2026-10-17 02:22Se creó el segundo índice (cola de impresión de facturas) en 3,5 segundos.ALTER TABLE bbf_facturas ADD INDEX …, ALGORITHM=INPLACE, LOCK=NONE.
2026-10-17 02:14 y 02:22Se comprobó que MySQL usa los índices nuevos.EXPLAIN: 164.400 → 1 fila (tareas) y 377.576 → 53.278 filas (facturas).
2026-10-17 y 10-18Se midió el servidor después de los cambios y se cancelaron las dos últimas consultas atascadas.Mediciones 1 y 2 (Resultados medidos), scripts en medicion/, KILL QUERY 1306; 1179; el 2026-10-18 03:01:23.

Los dos índices creados

ÍndiceTablaColumnasConsulta que acelera
idx_tasks_sede_donebbf_tasks(intId_Sede, dteDone)Tareas pendientes por sede
idx_facturas_sede_business_impresobbf_facturas(ID_SEDE, intId_Business, IMPRESO)Cola de impresión de facturas

Ninguno requiere cambios en el código de las aplicaciones.

Salvaguardas aplicadas en producción

  • Ventana de baja actividad: la ejecución se hizo de madrugada, entre las 02:09 y las 02:22.
  • Respaldo previo: Transversa-IT hizo una copia completa de la base de datos bigboss del servidor 200.118.190.188 antes de cualquier cambio, y se confirmó que terminó.
  • Creación en línea: ALGORITHM=INPLACE, LOCK=NONE. MySQL construye el índice mientras las aplicaciones siguen leyendo y escribiendo la tabla.
  • Tiempo máximo de espera de 5 segundos para el bloqueo breve de metadatos. El servidor tenía configurado un tiempo de espera de un año; sin esta guarda, una operación bloqueada habría dejado en cola a todas las consultas posteriores.
  • Un índice a la vez, empezando por la tabla pequeña, con verificación después de cada uno.

Ejecución paso a paso

Fecha y hora en formato aaaa-mm-dd hh:mm:ss, hora de Colombia, tomadas del registro de acciones de MySQL Workbench y del registro de estadísticas del servidor. Cada script está oculto: presiona "Ver script" para abrirlo. Se muestra tal como se ejecutó.

P0

💾 Respaldo completo de la base de datos

2026-10-17 01:09:52 → 02:08
Qué se hizo
Copia completa de la base de datos bigboss con la función Data Export de MySQL Workbench, ejecutada por Transversa-IT.
Dónde
Servidor 200.118.190.188, base de datos bigboss.
Archivo generado
E:\itBigBoss\Transversa-IT\BigbossBackup 20261017 0117.zip (el nombre indica fecha 2026-10-17 y hora 01:17).
Por qué
Es la red de seguridad. Aunque crear un índice no cambia datos, un respaldo reciente permite recuperar el estado anterior ante cualquier imprevisto.
Resultado esperado
Exportación terminada sin errores y archivo guardado fuera de la carpeta de análisis.
Resultado
Confirmado Transversa-IT informó a las 02:08 que el respaldo quedó listo.
P1

🩺 Verificaciones previas de solo lectura

2026-10-17 02:09:46
Ver script
SELECT
  (SELECT COUNT(*) FROM information_schema.innodb_trx)                           AS trx_abiertas,
  (SELECT COALESCE(MAX(TIMESTAMPDIFF(SECOND,trx_started,NOW())),0)
     FROM information_schema.innodb_trx)                                         AS trx_max_seg,
  (SELECT COUNT(*) FROM information_schema.processlist WHERE command<>'Sleep')   AS activas_incl_esta,
  (SELECT COALESCE(MAX(time),0) FROM information_schema.processlist
     WHERE command<>'Sleep')                                                     AS activa_max_seg,
  (SELECT COUNT(*) FROM information_schema.processlist
     WHERE command LIKE 'Binlog Dump%')                                          AS replicas_conectadas,
  @@log_bin AS log_bin, @@server_id AS server_id,
  @@lock_wait_timeout AS lock_wait, @@innodb_online_alter_log_max_size AS alter_log_max;
Por qué
Confirmar que no hay transacciones abiertas que impidan crear el índice, saber si existe una réplica donde el cambio también correría y conocer los tiempos de espera configurados.
Resultado esperado
Sin transacciones abiertas y sin réplicas conectadas.
Resultado
Correcto 0 transacciones abiertas · 0 réplicas conectadas · registro binario activo · lock_wait_timeout = 31.536.000 s (un año) · espacio para cambios en línea de 128 MB.
P2

👀 Revisión de consultas en ejecución

2026-10-17 02:10:26
Ver script
SELECT id, user, db, command, time, state, LEFT(info,100) AS consulta
FROM information_schema.processlist
WHERE command<>'Sleep' ORDER BY time DESC;
Por qué
Una consulta abierta mantiene un bloqueo de metadatos sobre sus tablas. Si una consulta larga está leyendo bbf_facturas, la creación del índice tendría que esperarla.
Resultado esperado
Solo consultas cortas, del orden de segundos.
Resultado
Hallazgo Tres consultas de búsqueda de personas (hilos 855, 857 y 934) llevaban entre 36.800 y 37.800 segundos ejecutándose, unas 10 horas, en estado statistics. Dos consultas de facturación corrían en ese momento, de 1 segundo.
P3

🗂️ Índice 1: tareas por sede

2026-10-17 02:13:53 · 2,619 s
Ver script
SET SESSION lock_wait_timeout = 5;
ALTER TABLE bbf_tasks
  ADD INDEX idx_tasks_sede_done (intId_Sede, dteDone),
  ALGORITHM=INPLACE, LOCK=NONE;
SHOW INDEX FROM bbf_tasks WHERE Key_name = 'idx_tasks_sede_done';
Por qué
Es la tabla más pequeña de las dos y la consulta 3 la lee completa cada vez. Se empieza aquí para validar el procedimiento con el menor riesgo.
Resultado esperado
Índice creado en pocos segundos, sin errores, con las dos columnas registradas.
Resultado
Correcto Creado en 2,619 s, 0 duplicados, 0 filas modificadas. SHOW INDEX devolvió las 2 columnas esperadas.

Entre la creación del índice 1 (P3) y su verificación (P4) se cancelaron tres consultas atascadas, el 2026-10-17 a las 02:14:39. Ese paso, con su script, está documentado en Consultas atascadas.

P4

✅ Verificación del índice 1

2026-10-17 02:14:56
Ver script
EXPLAIN SELECT T.intId FROM bbf_tasks AS T
 WHERE T.dteDone IS NULL AND T.intId_Sede = 1;
Por qué
EXPLAIN muestra el plan sin ejecutar la consulta. Permite comprobar que MySQL usa el índice nuevo.
Resultado esperado
Acceso por índice (ref) y un número de filas mucho menor que 164.400.
Resultado
Cumplido Acceso ref con idx_tasks_sede_done, 1 fila estimada, "Using index" (resuelto solo con el índice).
P5

🗂️ Índice 2: cola de impresión de facturas

2026-10-17 02:22:07 · 3,481 s
Ver script
SET SESSION lock_wait_timeout = 5;
ALTER TABLE bbf_facturas
  ADD INDEX idx_facturas_sede_business_impreso (ID_SEDE, intId_Business, IMPRESO),
  ALGORITHM=INPLACE, LOCK=NONE;
SHOW INDEX FROM bbf_facturas WHERE Key_name = 'idx_facturas_sede_business_impreso';
Por qué
La consulta 1 (82,5 % del tiempo) y la 2 (8,6 %) filtran bbf_facturas por sede y negocio. El índice permite ir directo a las facturas de la sede en lugar de leer toda la tabla.
Resultado esperado
Índice creado en segundos con las tres columnas registradas.
Resultado
Correcto Creado en 3,481 s, 0 duplicados. SHOW INDEX devolvió las 3 columnas esperadas.
P6

✅ Verificación del índice 2

2026-10-17 02:22:37
Ver script
EXPLAIN SELECT F.ID_FACTURA FROM bbf_facturas AS F
 WHERE (F.IMPRESO IS NULL OR DATE_FORMAT(F.IMPRESO,'%Y/%m/%d')='1900/01/01')
   AND F.FECHA >= '2018/11/19' AND F.intId_Business='1' AND F.ID_SEDE='1';
Por qué
Comprobar que la consulta real de la cola de impresión usa el índice nuevo.
Resultado esperado
Acceso por índice y una reducción clara de filas leídas. Se espera una mejora parcial, porque la función DATE_FORMAT sobre IMPRESO todavía impide filtrar por "no impreso" dentro del índice.
Resultado
Cumplido Acceso ref con idx_facturas_sede_business_impreso, 53.278 filas estimadas (antes 377.576). Mejora parcial, como se esperaba.

Cómo revertir

Si fuera necesario, cada índice se elimina en segundos y la base queda como estaba, sin pérdida de datos.

SET SESSION lock_wait_timeout = 5;
ALTER TABLE bbf_tasks    DROP INDEX idx_tasks_sede_done,                   ALGORITHM=INPLACE, LOCK=NONE;
ALTER TABLE bbf_facturas DROP INDEX idx_facturas_sede_business_impreso,    ALGORITHM=INPLACE, LOCK=NONE;

Consultas atascadas

Una consulta atascada es una búsqueda que lleva horas sin terminar. Mientras sigue abierta consume procesador, retiene bloqueos sobre las tablas que lee y puede impedir cambios como la creación de un índice. Esta sección registra cada consulta que se detectó, desde dónde se inicia, cuánto duró y cómo corregirla. Todas las horas son del servidor, hora de Colombia, formato de 24 horas.

5
consultas atascadas detectadas desde el 2026-10-16, todas canceladas
3
canceladas con KILL QUERY el 2026-10-17 02:14:39
2
canceladas con KILL QUERY el 2026-10-18 03:01:23
≈ 97 %
del tiempo acumulado de la búsqueda de personas lo explican solo las 3 canceladas

Registro de cancelaciones

HiloEstadoInicio aproximadoDuración hasta el KILLKILLUsuario y origen
855, 857, 934
tres hilos
Cancelados2026-10-16 entre 15:40 y 15:57≈ 10,3 a 10,6 h
37.053 a 38.044 s
2026-10-17 02:14:39No se registró el usuario de cada hilo
1306Cancelada2026-10-17 08:46:11≈ 18 h 15 min
65.712 s
2026-10-18 03:01:23soler desde localhost
1179Cancelada2026-10-17 12:42:37≈ 14 h 19 min
51.526 s
2026-10-18 03:01:23bigboss desde localhost

El inicio de 1306 y 1179 se calculó con la lectura de las 03:02:38, justo después de confirmar que seguían en la misma consulta (48.462 y 65.511 caracteres, estado statistics). Esa lectura corrige en 90 s la hora de inicio estimada antes. Tras el KILL, una nueva lectura de la lista de procesos no devolvió ninguna fila para los hilos 1306 y 1179, ni otras consultas de más de 10 minutos: las conexiones ya no aparecen.

Qué tienen en común

  • Es la misma consulta de búsqueda de personas (procedimiento find_Person): SELECT * FROM (SELECT P.ID_PERSONA, …. Es de solo lectura y no modifica datos.
  • Su texto es enorme. Mide 48.462 caracteres (hilo 1306) y 65.511 (hilo 1179). Una búsqueda normal es mucho más corta.
  • Arma una subconsulta por cada palabra escrita. En 1306 se ve hasta CRITERIO18, es decir, al menos 18 subconsultas unidas entre sí. Por el tamaño del texto, 1179 tendría cerca de 24. Cada una compara el criterio con unas 30 columnas usando LIKE '%…%', que no puede usar índices. El criterio visible en 1306 es '%co%', de solo dos letras, que coincide con casi cualquier nombre.
  • MySQL las muestra en estado statistics durante horas, no en executing. Es consistente con que el servidor siga eligiendo el orden de las uniones. La configuración actual lo permite: optimizer_search_depth = 62 (el máximo, que prueba combinaciones casi sin límite) y max_execution_time = 0 (sin límite de duración para ninguna consulta).
  • En uso normal la búsqueda es rápida. La estadística del servidor (desde 2026-10-14 07:48) registra 7.632 ejecuciones y 114.023,66 s acumulados. Las tres canceladas suman al menos 111.159 s, así que las otras 7.629 ejecuciones promediaron menos de 0,4 s.

Desde dónde se inicia

CapaDónde estáQué hace
PantallasAplicación Web, en Clientes/Specific.aspx, contacto_specific.aspx, Debito_Automatico/new_Contract.aspx, CRM/new_Courtesy.aspx, CRM/Lista_Negra.aspx, CRM/Tareas.aspx y Horarios/ (Default, Profesionales, Salones_Disponibilidad, Schedule_WC)El botón de la lupa llama la función JavaScript find_Person() con el texto escrito.
Servicio webApp_Code/ws_Personas_Find.vb, función dtbFind_Persona (línea 18)Parte el texto por espacios (líneas 27 a 53), sin límite de palabras, y llama a find_Person en la línea 82.
Llamadas directasGastos/Expenses.aspx.vb (línea 863) e Inventarios/Compras.aspx.vb (línea 116)Llaman find_Person con el mismo esquema de palabras.
ProcedimientoBase de datos bigboss, procedimiento find_PersonConstruye el texto SQL con una subconsulta por palabra.
Revisar tambiéncontactos.aspx.vb (línea 128) y Clientes/Default.aspx.vb (línea 133)Usan find_Person_filter, un procedimiento parecido que no se analizó todavía.
Aplicación WindowsRepositorio Soler-AppWinNo hay llamadas a find_Person.
Origen de las conexionesSesiones 1306 y 1179Las dos últimas sesiones (1306 y 1179) se conectaban desde localhost, es decir, desde el mismo servidor que la base de datos, lo que es compatible con la aplicación Web.
Usuarios de base de datosHilo 1306 y hilo 1179El hilo 1306 usa el usuario soler y 1179 el usuario bigboss, así que parecen dos aplicaciones o configuraciones distintas.

Consultas, una por una

K1

Hilos 855, 857 y 934

KILL 2026-10-17 02:14:39
Estado
Cancelados
Inicio
2026-10-16, entre las 15:40 y las 15:57 (viernes por la tarde), los tres con pocos minutos de diferencia.
Tiempo hasta el KILL
Entre 37.053 y 38.044 s, es decir, de 10 h 17 min a 10 h 34 min. El mayor coincide con el máximo que registró el servidor para esta consulta: 38.043,65 s.
Por qué se cancelaron
Llevaban unas 10 horas sin terminar, consumiendo recursos del servidor y reteniendo bloqueos que habrían detenido la creación del segundo índice. Antes de cancelarlas se confirmó que eran las mismas consultas, con los mismos tiempos.
Cómo se detectaron
En la revisión de consultas en ejecución del paso P2 de Ejecución paso a paso (02:10:26), antes de crear el segundo índice. Estado statistics. Los tres hilos tenían las mismas características: misma consulta y tiempos entre 36.800 y 37.800 s.
Comando
Ejecutado el 2026-10-17 a las 02:14:39, entre la creación del índice 1 y su verificación, con autorización expresa. Corta la consulta y no cierra la conexión de la aplicación. Son consultas de lectura y no modifican datos.
Ver script
KILL QUERY 855;
KILL QUERY 857;
KILL QUERY 934;
Resultado
La lista de procesos quedó sin consultas largas. Las aplicaciones siguieron conectadas.
Datos que no se registraron
El usuario, el equipo de origen y el texto de búsqueda de cada hilo. En la próxima cancelación se guardarán con el script 02_consultas_largas.sql.
K2

Hilo 1306

KILL 2026-10-18 03:01:23
Estado
Cancelada
Inicio
2026-10-17 08:46:11 (sábado por la mañana), calculado con la duración leída a las 03:02:38.
Tiempo hasta el KILL
18 h 15 min 12 s (65.712 s).
Usuario y origen
Usuario soler, conexión desde localhost:55967, base bigboss.
Qué ejecuta
Búsqueda de personas con al menos 18 criterios (CRITERIO1 a CRITERIO18). Texto de 48.462 caracteres. Criterio visible: LIKE '%co%'. Estado statistics.
Comando
KILL QUERY 1306; Ejecutado con autorización expresa a las 03:01:23, después de confirmar en la lista de procesos que el hilo seguía en la misma consulta.
Resultado
Sin filas para este hilo en la lista de procesos en la lectura posterior.
Cómo corregirla
Se corrige en la fase 3 del proyecto (ver Costos del proyecto).
K3

Hilo 1179

KILL 2026-10-18 03:01:23
Estado
Cancelada
Inicio
2026-10-17 12:42:37 (sábado al mediodía), calculado con la duración leída a las 03:02:38.
Tiempo hasta el KILL
14 h 18 min 46 s (51.526 s).
Usuario y origen
Usuario bigboss, conexión desde localhost:57554, base bigboss.
Qué ejecuta
La misma búsqueda de personas, con un texto de 65.511 caracteres. Por el tamaño tendría cerca de 24 criterios (estimación). Estado statistics.
Comando
KILL QUERY 1179; Ejecutado con autorización expresa a las 03:01:23, después de confirmar en la lista de procesos que el hilo seguía en la misma consulta.
Resultado
Sin filas para este hilo en la lista de procesos en la lectura posterior.
Cómo corregirla
Se corrige en la fase 3 del proyecto (ver Costos del proyecto).

Resultados medidos

Comparación de filas que MySQL estima leer por ejecución, con la misma consulta y los mismos parámetros, antes y después.

Tareas pendientes por sede (bbf_tasks)

Antes164.400
Después1

De lectura completa de la tabla a una lectura directa por índice.

Cola de impresión de facturas (bbf_facturas)

Antes377.576
Después53.278

7,1 veces menos filas. Las barras están a escala dentro de cada consulta.

ConsultaAntesDespués
bbf_tasksAcceso ALL · sin índice · 164.400 filasAcceso ref · idx_tasks_sede_done · 1 fila
bbf_facturasAcceso ALL · sin índice · 377.576 filas · 0,01 % útilesAcceso ref · idx_facturas_sede_business_impreso · 53.278 filas · 33,33 % útiles

Evolución medida del servidor

Tiempo real por ejecución de las tres consultas más pesadas. Cada vez que revisemos el servidor se agrega una columna con el mismo método: la misma consulta SQL y dos lecturas separadas unos 15 minutos, de las que se calcula el promedio de ese periodo.

Segundos por ejecución (escala logarítmica)

Cargando mediciones…

Escala logarítmica: cada línea horizontal vale diez veces la anterior. Más abajo es más rápido.

Consultas simultáneas promedio en el servidor

Tiempo total de consultas dividido por el tiempo del periodo medido. El valor del periodo posterior corresponde a una carga menor (sábado al mediodía); la comparación definitiva es la medición de un día hábil en hora pico.

Comparativo por medición
Cargando…

Impacto operativo

  • Ninguna tabla se bloqueó para lectura o escritura durante la creación de los índices.
  • No se modificó ningún dato ni ninguna estructura de las aplicaciones.
  • Las consultas de más de 10 horas se cancelaron sin cerrar las conexiones de las aplicaciones.
  • Los índices añaden un costo pequeño a cada inserción o actualización de esas dos tablas. Para este volumen se considera despreciable frente a la lectura completa que evitan.

Pendiente de validar en 24 a 48 horas

Para cerrar la mejora con evidencia sobre el uso real, se repetirá la exportación de las consultas más costosas con el mismo método de la línea base (2026-10-16 12:32) y se comparará.

MedidaLínea base (2026-10-16)Qué se espera ver
Tiempo promedio por ejecución, consulta 1 (cola de impresión)≈ 0,40 s por ejecución (418.543 s en 1.042.326 ejecuciones)Descenso visible; mayor aún tras el ajuste de código
Filas examinadas por ejecución, consulta 1≈ 483.000Del orden de las 53.000 o menos
Filas examinadas por ejecución, consulta 3 (tareas)≈ 557.000Cercano a las filas realmente pendientes de la sede
Consultas sin índice, ejecuciones del top 1001,38 millones de 2,40 millonesReducción marcada en las consultas 1, 2 y 3
Tiempo total de base de datos por hora real≈ 2,7 consultas simultáneas en promedioDescenso proporcional al peso de las 3 consultas (95,8 %)
⚖️ Alcance honesto de la mejora

La mejora en consultas 1 y 2 es parcial hasta corregir la condición de IMPRESO en el código. La percepción de rapidez de los usuarios también depende de la red, de los equipos de las sedes y de otras consultas del top 100 que aún no se han tocado.