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);
|
||||
$turnos = $stmtTurnos->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// ── Enriquecer con exámenes y consentimientos ──────────────────
|
||||
foreach ($turnos as &$turno) {
|
||||
// Exámenes
|
||||
// ── Enriquecer con exámenes, consentimientos y comentarios (batch) ─
|
||||
$turnoIds = array_column($turnos, 'id');
|
||||
$examenes = [];
|
||||
$consentimientos = [];
|
||||
$comentarios = [];
|
||||
|
||||
if ($turnoIds) {
|
||||
$ph = implode(',', array_fill(0, count($turnoIds), '?'));
|
||||
|
||||
// Exámenes — batch
|
||||
$stmtExam = $pdo->prepare(
|
||||
"SELECT DISTINCT et.nombre, et.codigo
|
||||
FROM turnero_examen_items tei
|
||||
"SELECT ts.turno_id, et.nombre, et.codigo
|
||||
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
|
||||
WHERE tei.solicitud_id = (
|
||||
SELECT id FROM turnero_solicitudes WHERE turno_id = ? LIMIT 1
|
||||
)
|
||||
WHERE ts.turno_id IN ($ph)
|
||||
ORDER BY et.nombre ASC"
|
||||
);
|
||||
$stmtExam->execute([(int)$turno['id']]);
|
||||
$turno['examenes'] = $stmtExam->fetchAll(PDO::FETCH_ASSOC);
|
||||
$stmtExam->execute($turnoIds);
|
||||
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(
|
||||
"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
|
||||
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"
|
||||
);
|
||||
$stmtCons->execute([(int)$turno['id']]);
|
||||
$turno['consentimientos'] = $stmtCons->fetchAll(PDO::FETCH_ASSOC);
|
||||
$stmtCons->execute($turnoIds);
|
||||
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(
|
||||
"SELECT usuario_nombre, comentario, tipo, creado_at
|
||||
FROM turnero_comentarios
|
||||
WHERE turno_id = ?
|
||||
ORDER BY creado_at DESC
|
||||
LIMIT 3"
|
||||
"SELECT tc.turno_id, tc.usuario_nombre, tc.comentario, tc.tipo, tc.creado_at
|
||||
FROM turnero_comentarios tc
|
||||
WHERE tc.turno_id IN ($ph)
|
||||
ORDER BY tc.turno_id, tc.creado_at DESC"
|
||||
);
|
||||
$stmtCom->execute([(int)$turno['id']]);
|
||||
$turno['comentarios'] = $stmtCom->fetchAll(PDO::FETCH_ASSOC);
|
||||
$stmtCom->execute($turnoIds);
|
||||
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) ───────────────────
|
||||
|
||||
Reference in New Issue
Block a user