perf(historial): reemplazar N+1 queries por 3 batch queries
Las 3 subqueries por turno (examenes, consentimientos, comentarios) × 50 turnos = 150 round-trips al servidor remoto (~83ms c/u) sumaban 12.5s de espera, causando timeouts o página sin carga. Ahora se agrupan en 3 queries con IN(?) sobre todos los IDs del lote. Tiempo total: ~357ms (35x más rápido). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
70fda3dacc
commit
dffb242522
@@ -136,42 +136,67 @@ $stmtTurnos = $pdo->prepare($sqlTurnos);
|
|||||||
$stmtTurnos->execute($bindsPage);
|
$stmtTurnos->execute($bindsPage);
|
||||||
$turnos = $stmtTurnos->fetchAll(PDO::FETCH_ASSOC);
|
$turnos = $stmtTurnos->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// ── Enriquecer con exámenes y consentimientos ──────────────────
|
// ── Enriquecer con exámenes, consentimientos y comentarios (batch) ─
|
||||||
foreach ($turnos as &$turno) {
|
$turnoIds = array_column($turnos, 'id');
|
||||||
// Exámenes
|
$examenes = [];
|
||||||
|
$consentimientos = [];
|
||||||
|
$comentarios = [];
|
||||||
|
|
||||||
|
if ($turnoIds) {
|
||||||
|
$ph = implode(',', array_fill(0, count($turnoIds), '?'));
|
||||||
|
|
||||||
|
// Exámenes — batch
|
||||||
$stmtExam = $pdo->prepare(
|
$stmtExam = $pdo->prepare(
|
||||||
"SELECT DISTINCT et.nombre, et.codigo
|
"SELECT ts.turno_id, et.nombre, et.codigo
|
||||||
FROM turnero_examen_items tei
|
FROM turnero_solicitudes ts
|
||||||
|
JOIN turnero_examen_items tei ON tei.solicitud_id = ts.id
|
||||||
JOIN exam_tipos et ON et.id = tei.exam_tipo_id
|
JOIN exam_tipos et ON et.id = tei.exam_tipo_id
|
||||||
WHERE tei.solicitud_id = (
|
WHERE ts.turno_id IN ($ph)
|
||||||
SELECT id FROM turnero_solicitudes WHERE turno_id = ? LIMIT 1
|
|
||||||
)
|
|
||||||
ORDER BY et.nombre ASC"
|
ORDER BY et.nombre ASC"
|
||||||
);
|
);
|
||||||
$stmtExam->execute([(int)$turno['id']]);
|
$stmtExam->execute($turnoIds);
|
||||||
$turno['examenes'] = $stmtExam->fetchAll(PDO::FETCH_ASSOC);
|
foreach ($stmtExam->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
||||||
|
$examenes[(int)$row['turno_id']][] = ['nombre' => $row['nombre'], 'codigo' => $row['codigo']];
|
||||||
|
}
|
||||||
|
|
||||||
// Consentimientos
|
// Consentimientos — batch
|
||||||
$stmtCons = $pdo->prepare(
|
$stmtCons = $pdo->prepare(
|
||||||
"SELECT tc.id, f.nombre, tc.estado, tc.firmado_at
|
"SELECT tc.turno_id, tc.id, f.nombre, tc.estado, tc.firmado_at
|
||||||
FROM turnero_consentimientos tc
|
FROM turnero_consentimientos tc
|
||||||
LEFT JOIN lab_formularios f ON f.id = tc.formulario_id
|
LEFT JOIN lab_formularios f ON f.id = tc.formulario_id
|
||||||
WHERE tc.turno_id = ?
|
WHERE tc.turno_id IN ($ph)
|
||||||
ORDER BY tc.estado DESC, tc.firmado_at DESC"
|
ORDER BY tc.estado DESC, tc.firmado_at DESC"
|
||||||
);
|
);
|
||||||
$stmtCons->execute([(int)$turno['id']]);
|
$stmtCons->execute($turnoIds);
|
||||||
$turno['consentimientos'] = $stmtCons->fetchAll(PDO::FETCH_ASSOC);
|
foreach ($stmtCons->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
||||||
|
$tid = (int)$row['turno_id'];
|
||||||
|
unset($row['turno_id']);
|
||||||
|
$consentimientos[$tid][] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
// Comentarios
|
// Comentarios — batch (últimos 3 por turno via subquery)
|
||||||
$stmtCom = $pdo->prepare(
|
$stmtCom = $pdo->prepare(
|
||||||
"SELECT usuario_nombre, comentario, tipo, creado_at
|
"SELECT tc.turno_id, tc.usuario_nombre, tc.comentario, tc.tipo, tc.creado_at
|
||||||
FROM turnero_comentarios
|
FROM turnero_comentarios tc
|
||||||
WHERE turno_id = ?
|
WHERE tc.turno_id IN ($ph)
|
||||||
ORDER BY creado_at DESC
|
ORDER BY tc.turno_id, tc.creado_at DESC"
|
||||||
LIMIT 3"
|
|
||||||
);
|
);
|
||||||
$stmtCom->execute([(int)$turno['id']]);
|
$stmtCom->execute($turnoIds);
|
||||||
$turno['comentarios'] = $stmtCom->fetchAll(PDO::FETCH_ASSOC);
|
foreach ($stmtCom->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
||||||
|
$tid = (int)$row['turno_id'];
|
||||||
|
if (!isset($comentarios[$tid])) $comentarios[$tid] = [];
|
||||||
|
if (count($comentarios[$tid]) < 3) {
|
||||||
|
unset($row['turno_id']);
|
||||||
|
$comentarios[$tid][] = $row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($turnos as &$turno) {
|
||||||
|
$tid = (int)$turno['id'];
|
||||||
|
$turno['examenes'] = $examenes[$tid] ?? [];
|
||||||
|
$turno['consentimientos'] = $consentimientos[$tid] ?? [];
|
||||||
|
$turno['comentarios'] = $comentarios[$tid] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Resumen por estado (del rango filtrado) ───────────────────
|
// ── Resumen por estado (del rango filtrado) ───────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user