optimise MariaDB : deux index confirmés par EXPLAIN, N+1 supprimé

Jeu de données de charge (500 classes, 20 000 élèves, 30 000 sessions
de lab) généré localement contre une MariaDB jetable, jamais en
production, via la nouvelle commande charge:generer (refuse de
tourner si APP_ENV=production).

EXPLAIN confirme deux manques réels : lab_sessions.etat (30 056 lignes
parcourues sans index, lu chaque minute par l'expiration des sessions
et le self-healing) et classes.archivee_a (lu chaque jour par la purge
RGPD). devoirs.echeance n'avait besoin de rien : l'index existant sur
classe_id suffisait déjà, EXPLAIN l'a confirmé plutôt que d'ajouter un
index inutile.

ResultatsController faisait une requête de corrections et une
d'observations par classe du prof (N+1) : remplacé par une requête de
chaque pour toutes les classes, regroupées en mémoire.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Adam Belkacemi 2026-10-14 09:31:11 +02:00
parent ca544ac620
commit e35e0e3c0b
5 changed files with 305 additions and 6 deletions

View file

@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Optimisation MariaDB (bloc B, 2026-10-14) : deux manques confirmés par
* EXPLAIN sur un jeu de données de charge (500 classes, 20 000 élèves,
* 30 000 sessions de lab — `php artisan charge:generer`, jamais en
* production), pas devinés. `lab_sessions.etat` faisait un parcours complet
* de la table (`type: ALL`, 30 056 lignes) : lu chaque minute par
* ExpirerSessionsLab et SurveillanceVm. `classes.archivee_a` aussi
* (`type: ALL`), lu chaque jour par la purge RGPD. En comparaison,
* `devoirs.echeance` s'appuyait déjà bien sur l'index existant de
* `classe_id` (2 lignes examinées) : pas touché, un index de plus n'aurait
* rien amélioré.
*/
return new class extends Migration
{
public function up(): void
{
Schema::table('lab_sessions', function (Blueprint $table) {
$table->index('etat');
});
Schema::table('classes', function (Blueprint $table) {
$table->index('archivee_a');
});
}
public function down(): void
{
Schema::table('lab_sessions', function (Blueprint $table) {
$table->dropIndex(['etat']);
});
Schema::table('classes', function (Blueprint $table) {
$table->dropIndex(['archivee_a']);
});
}
};