perf: batch per-record translation preload in t()

t() issued one SELECT per translated field (1,300+ queries on a typical
multilanguage home). It now preloads all translations of a (table,
record, language) in a single query and serves subsequent fields from
memory, preserving the previous LIMIT 1 semantics (first row per
fieldName). Measured on villagrancanaria: cold render -60% (en home)
/ -67% (es home), byte-identical output.

REQUIRES index (tableName, recordNum, prefix) on cms_traducciones —
without it the batched query scans and is SLOWER than before:
ALTER TABLE cms_traducciones ADD INDEX idx_tabla_registro_prefijo (tableName, recordNum, prefix);
This commit is contained in:
Jordan Diaz
2026-07-21 18:29:46 +00:00
parent 432130565b
commit bcd21dd274

View File

@@ -182,7 +182,23 @@ function t($record, $campo = "title", $options = array(), $idioma=null){
if (@$record["urlPath"] || @$record["info1"]){
$recordtr = $DB->fetch("SELECT fieldValue FROM {$TABLE_PREFIX}traducciones WHERE tableName='uploads' AND recordNum=? AND fieldName=? AND prefix=? AND uploadNum=? LIMIT 1", [$record['recordNum'], $campo, @$idioma, $record['num']]);
}else{
$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]);
// Precarga por REGISTRO: una unica query trae todas las traducciones
// del (tabla, num, idioma) y las siguientes llamadas a t() sobre el
// mismo registro salen de memoria. Sin esto, cada campo traducido
// lanzaba su propio SELECT (1.300+ queries en una home tipica).
// Semantica identica al SELECT ... LIMIT 1 anterior: se conserva la
// primera fila por fieldName.
global $__traduccionesPorRegistro;
$__trKey = @$record['tableName']."|".@$record['num']."|".$idioma;
if (!isset($__traduccionesPorRegistro[$__trKey])){
$__trRows = $DB->executeS("SELECT fieldName, fieldValue FROM {$TABLE_PREFIX}traducciones WHERE tableName=? AND recordNum=? AND prefix=?", [@$record['tableName'], @$record['num'], $idioma]);
$__trMap = array();
foreach ((array)$__trRows as $__trRow){
if (!isset($__trMap[$__trRow['fieldName']])) $__trMap[$__trRow['fieldName']] = $__trRow['fieldValue'];
}
$__traduccionesPorRegistro[$__trKey] = $__trMap;
}
$recordtr = isset($__traduccionesPorRegistro[$__trKey][$campo]) ? array("fieldValue" => $__traduccionesPorRegistro[$__trKey][$campo]) : null;
}
if ($recordtr) {
$trad = CocoParser::parsea_codigos_en_linea(parsea_texto2($recordtr["fieldValue"]),$options);