- BDD (migrations 1.6.0 + 1.7.0, idempotentes) :
* 4 nouveaux index composites sur reactevents, triggerevents, sessions
* vue sessiondebriefs reecrite (sous-requetes correlees -> JOINs)
puis materialisee dans table session_debriefs_cache via procedure
stockee rebuild_debrief_cache, recalculee uniquement aux changements
* fix bug double JOIN participates : TargetRole = "IA" pour les hits
NPC/objets (au lieu d'un role aleatoire de participant)
- API PHP :
* connexion PDO en singleton + ATTR_PERSISTENT
* cache disque par session (cache/sess_<id>/) pour debrief, get, userhistory
avec invalidation ciblee sur events et lifecycle
* pagination opt-in (limit/offset) sur lists/sessions_for_user
* helpers ensure_/rebuild_/invalidate_session_debrief_cache_db
* debug/benchmark.php pour mesurer la latence des 6 endpoints cles
- Endpoints HTTP : signatures inchangees, compat Unreal preservee
- Gain mesure : -58% a -83% sur les 5 endpoints cles
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
127 lines
6.1 KiB
SQL
127 lines
6.1 KiB
SQL
-- ============================================================
|
|
-- Migration 1.6.0 - Optimisation des temps de reponse
|
|
-- ============================================================
|
|
-- Cible : MariaDB 10.4+ (XAMPP local).
|
|
-- Idempotent : ce fichier peut etre rejoue sans erreur sur n'importe quel poste.
|
|
-- Aucun changement de structure : seuls des index sont ajoutes
|
|
-- (via une procedure stockee qui teste leur presence) et la vue
|
|
-- sessiondebriefs est redefinie via CREATE OR REPLACE VIEW.
|
|
-- ============================================================
|
|
|
|
USE proserveapi;
|
|
|
|
-- ------------------------------------------------------------
|
|
-- Procedure helper : ajoute un index seulement s'il n'existe pas
|
|
-- (CREATE INDEX IF NOT EXISTS n'est dispo qu'a partir de MariaDB 10.5.4)
|
|
-- ------------------------------------------------------------
|
|
DROP PROCEDURE IF EXISTS create_index_if_missing;
|
|
|
|
DELIMITER $$
|
|
CREATE PROCEDURE create_index_if_missing(
|
|
IN p_table VARCHAR(64),
|
|
IN p_index VARCHAR(64),
|
|
IN p_cols VARCHAR(255)
|
|
)
|
|
BEGIN
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM information_schema.STATISTICS
|
|
WHERE TABLE_SCHEMA = DATABASE()
|
|
AND TABLE_NAME = p_table
|
|
AND INDEX_NAME = p_index
|
|
) THEN
|
|
SET @sql = CONCAT('ALTER TABLE `', p_table, '` ADD INDEX `', p_index, '` (', p_cols, ')');
|
|
PREPARE stmt FROM @sql;
|
|
EXECUTE stmt;
|
|
DEALLOCATE PREPARE stmt;
|
|
END IF;
|
|
END$$
|
|
DELIMITER ;
|
|
|
|
-- ------------------------------------------------------------
|
|
-- Index manquants identifies a l'analyse des requetes lourdes
|
|
-- ------------------------------------------------------------
|
|
|
|
-- JOIN reactevents <-> triggerevents : la cle composite la plus utilisee
|
|
CALL create_index_if_missing('reactevents', 'idx_react_session_event', '`srcEventSessionId`, `srcEventIndex`');
|
|
|
|
-- Filtres "tirs d'un user dans une session" (stats_object getShotsFiredByUser, getTargetKilledInSession)
|
|
CALL create_index_if_missing('triggerevents', 'idx_trigger_session_user', '`sessionId`, `srcUserId`');
|
|
|
|
-- Agregation NbKilled (auto-jointure RK dans la vue sessiondebriefs)
|
|
CALL create_index_if_missing('reactevents', 'idx_react_killed', '`targetKilled`, `srcEventSessionId`');
|
|
|
|
-- Tri/filtrage des sessions par date (listes recentes)
|
|
CALL create_index_if_missing('sessions', 'idx_sessions_date', '`sessionDate` DESC');
|
|
|
|
-- Nettoyage de la procedure helper
|
|
DROP PROCEDURE create_index_if_missing;
|
|
|
|
|
|
-- ------------------------------------------------------------
|
|
-- Redefinition de la vue sessiondebriefs (idempotent via CREATE OR REPLACE)
|
|
-- ------------------------------------------------------------
|
|
-- Modifications par rapport a la definition d'origine :
|
|
-- - Suppression des wraps "(SELECT IFNULL(...))" qui forcaient une evaluation par row
|
|
-- -> remplaces par IFNULL(...) directement (semantique identique).
|
|
-- - Suppression des sous-requetes correlees (SELECT R.displayName FROM userroles R WHERE R.id = ...)
|
|
-- -> remplacees par deux LEFT JOIN explicites sur userroles (URS et URT).
|
|
-- - Tous les autres JOIN, le GROUP BY et l'ORDER BY restent strictement identiques
|
|
-- pour preserver le contrat de sortie (memes colonnes, memes lignes, memes valeurs).
|
|
-- ------------------------------------------------------------
|
|
|
|
CREATE OR REPLACE VIEW sessiondebriefs AS
|
|
SELECT
|
|
S.id AS SessionId,
|
|
S.sessionType AS SessionTypeId,
|
|
ST.displayName AS SessionType,
|
|
S.sessionName AS SessionName,
|
|
S.sessionDate AS SessionDate,
|
|
S.mapName AS MapName,
|
|
S.scenarioName AS ScenarioName,
|
|
S.success AS SessionSuccessful,
|
|
S.timeToFinish AS SessionDuration,
|
|
COALESCE(T.type, -1) AS TriggerTypeId,
|
|
COALESCE(TT.displayName, '') AS TriggerType,
|
|
IFNULL(T.srcUserId, PS.userId) AS ShooterId,
|
|
US.username AS ShooterName,
|
|
IFNULL(PS.role, 3) AS ShooterRoleId,
|
|
URS.displayName AS ShooterRole,
|
|
COALESCE(T.indexCount, -1) AS ShotIndex,
|
|
COALESCE(R.id, -1) AS ReactId,
|
|
COALESCE(R.reactMode, 2) AS ReactModeId,
|
|
COALESCE(RM.displayName, '') AS ReactMode,
|
|
COALESCE(R.reactType, -1) AS ReactTypeId,
|
|
COALESCE(RT.displayName, '') AS ReactType,
|
|
COALESCE(R.hitUserId, -1) AS TargetUserId,
|
|
COALESCE(UH.username, '') AS TargetUserName,
|
|
IFNULL(PH.role, 3) AS TargetRoleId,
|
|
URT.displayName AS TargetRole,
|
|
COALESCE(R.hitTargetName, '') AS TargetName,
|
|
COALESCE(R.hitBoneName, '') AS TargetBoneName,
|
|
COALESCE(R.targetKilled, 0) AS TargetKilled,
|
|
COALESCE(R.objectHitLocationX, 0) AS HitLocationX,
|
|
COALESCE(R.objectHitLocationY, 0) AS HitLocationY,
|
|
COALESCE(R.objectHitTagLocation, '') AS HitLocationTag,
|
|
COALESCE(R.hitPrecision, 0) AS HitPrecision,
|
|
COALESCE(R.distance, 0) AS HitTargetDistance,
|
|
COALESCE(R.reactTime, 0) AS ReactionTime,
|
|
COALESCE(R.timeStamp, 0) AS TimeStamp,
|
|
COUNT(DISTINCT R.id) AS NbHit,
|
|
COUNT(DISTINCT RK.srcEventIndex, RK.hitTargetName) AS NbKilled
|
|
FROM sessions S
|
|
LEFT JOIN participates PS ON (S.id = PS.sessionId)
|
|
LEFT JOIN participates PH ON (S.id = PH.sessionId)
|
|
LEFT JOIN triggerevents T ON (S.id = T.sessionId)
|
|
LEFT JOIN triggereventtypes TT ON (TT.id = T.type)
|
|
LEFT JOIN sessiontypes ST ON (ST.id = S.sessionType)
|
|
LEFT JOIN reactevents R ON (T.indexCount = R.srcEventIndex AND T.sessionId = R.srcEventSessionId)
|
|
LEFT JOIN users UH ON (UH.id = R.hitUserId)
|
|
LEFT JOIN users US ON (US.id = T.srcUserId OR US.id = PS.userId)
|
|
LEFT JOIN reacteventtypes RT ON (RT.id = R.reactType)
|
|
LEFT JOIN reacteventmodes RM ON (RM.id = COALESCE(R.reactMode, 2))
|
|
LEFT JOIN reactevents RK ON (R.id = RK.id AND RK.targetKilled = 1)
|
|
LEFT JOIN userroles URS ON (URS.id = IFNULL(PS.role, 3))
|
|
LEFT JOIN userroles URT ON (URT.id = IFNULL(PH.role, 3))
|
|
GROUP BY SessionId, ShooterId, ShotIndex, TargetName
|
|
ORDER BY SessionId, ShooterId, ShotIndex, ReactId;
|