perf: self-provision the traducciones index required by batched t()

The batched translation preload requires the (tableName, recordNum,
prefix) index; without it the per-record query scans and is slower
than the legacy per-field lookup. t() now checks once per PHP process
(static) whether idx_tabla_registro_prefijo exists, creates it on the
fly when the DB user has ALTER rights (re-checking after a lost race),
and otherwise falls back to the legacy per-field query — never slower
than the original behavior on webs where the index cannot be created.

Verified live: dropped the index on villagrancanaria local, first
request recreated it automatically and subsequent renders stayed fast.
This commit is contained in:
Jordan Diaz
2026-07-21 18:34:10 +00:00
parent bcd21dd274
commit 34d1458f3a

View File

@@ -188,6 +188,34 @@ function t($record, $campo = "title", $options = array(), $idioma=null){
// lanzaba su propio SELECT (1.300+ queries en una home tipica). // lanzaba su propio SELECT (1.300+ queries en una home tipica).
// Semantica identica al SELECT ... LIMIT 1 anterior: se conserva la // Semantica identica al SELECT ... LIMIT 1 anterior: se conserva la
// primera fila por fieldName. // primera fila por fieldName.
// Auto-comprobacion del indice requerido: una vez por proceso PHP.
// Si falta, se intenta crear aqui mismo (las webs suelen tener
// permisos de ALTER sobre su propia BD); si no se puede, se cae al
// modo clasico por campo — nunca mas lento que el comportamiento
// original. En caso de carrera entre workers, el perdedor del
// ALTER re-verifica antes de rendirse.
static $__trIndexOk = null;
if ($__trIndexOk === null){
try{
$__idxRow = $DB->fetch("SELECT COUNT(*) c FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = '{$TABLE_PREFIX}traducciones' AND index_name = 'idx_tabla_registro_prefijo'");
$__trIndexOk = intval(@$__idxRow['c']) > 0;
if (!$__trIndexOk){
try{
$DB->execute("ALTER TABLE {$TABLE_PREFIX}traducciones ADD INDEX idx_tabla_registro_prefijo (tableName, recordNum, prefix)");
$__trIndexOk = true;
}catch(\Throwable $__eAlter){
$__idxRow = $DB->fetch("SELECT COUNT(*) c FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = '{$TABLE_PREFIX}traducciones' AND index_name = 'idx_tabla_registro_prefijo'");
$__trIndexOk = intval(@$__idxRow['c']) > 0;
}
}
}catch(\Throwable $__eIdx){
$__trIndexOk = false;
}
}
if (!$__trIndexOk){
// Modo clasico (sin indice): query por campo, como siempre.
$recordtr = $DB->fetch("SELECT fieldValue FROM {$TABLE_PREFIX}traducciones WHERE tableName=? AND recordNum=? AND fieldName=? AND prefix=? LIMIT 1", [@$record['tableName'], @$record['num'], $campo, @$idioma]);
}else{
global $__traduccionesPorRegistro; global $__traduccionesPorRegistro;
$__trKey = @$record['tableName']."|".@$record['num']."|".$idioma; $__trKey = @$record['tableName']."|".@$record['num']."|".$idioma;
if (!isset($__traduccionesPorRegistro[$__trKey])){ if (!isset($__traduccionesPorRegistro[$__trKey])){
@@ -200,6 +228,7 @@ function t($record, $campo = "title", $options = array(), $idioma=null){
} }
$recordtr = isset($__traduccionesPorRegistro[$__trKey][$campo]) ? array("fieldValue" => $__traduccionesPorRegistro[$__trKey][$campo]) : null; $recordtr = isset($__traduccionesPorRegistro[$__trKey][$campo]) ? array("fieldValue" => $__traduccionesPorRegistro[$__trKey][$campo]) : null;
} }
}
if ($recordtr) { if ($recordtr) {
$trad = CocoParser::parsea_codigos_en_linea(parsea_texto2($recordtr["fieldValue"]),$options); $trad = CocoParser::parsea_codigos_en_linea(parsea_texto2($recordtr["fieldValue"]),$options);
$hashTraducciones[$hash] = $trad; $hashTraducciones[$hash] = $trad;