Gestion efficace de la table de données sur le nombre de participants


Je lis de la documentation sur la gestion de tables temporaires et voici ce que j’en retiens …

TRUNCATE est plus efficace que DELETE pour VIDER UNE TABLE

DELETE fait une suppression ligne par ligne, alors que TRUNCATE vide la table et remet l’increment à 1 au passage.

En MySQL, les opérations de DELETE sont réversibles, alors que celles de TRUNCATE ne le sont pas. En PosgreSQL, les deux types de suppression sont réversibles.

Apparemment, le fonction delete_records() de Moodle sans condition fait un TRUNCATE, mais le résultat peut poser problème :
https://tracker.moodle.org/browse/MDL-64763

Je vais donc faire un DROP TABLE et recréer la table.

Nourrir la table de données sur le nombre de participants

La plus simple semble être de vider la table chaque nuit pour recalculer toutes les données. Je fais préalablement le ménage dans les données de log puis j’extrais les données sur les courseid qui m’intéressent :

select distinct(courseid) from mdl_logstore_socialflow_hits_log;

Cette requête coûte quand même 250ms !
Et dans mon cas, j’ai 4200 lignes pour 8300 cours.
C’est assez logique dans la mesure où les cours sont organisés par quadri, il y a la moitié des cours qui sont actifs.
Ca veut la peine d’extraire juste la liste des cours actifs.

Comment gérer la mise à jour des informations dans la table des courseid ?
Je décide de travailler avec une table temporaire qui repart des courseid qui existent dans la table des logs.
Et voici un script qui parse les id de cours, recalcule le nombre de participants et stocke le tout dans une table temporaire, avant de remplacer le contenu de la table de gestion du nombre de participants pas cours.

$connexion = pg_connect("host=$host port=$port dbname=$dbname user=$username password=$password");

if (!$connexion) {
    echo "Erreur de connexion.\n";
    exit;
}

echo "Connexion réussie !";
  

$sql ="CREATE TABLE temp_logstore_socialflow_nbpa (courseid BIGINT, nbpa BIGINT)";
$result = pg_query($connexion,$sql);
if (!$result) die("temporary table creation impossible");

$sql2 ="SELECT DISTINCT(courseid) FROM mdl_logstore_socialflow_log";
$result2 = pg_query($connexion,$sql2);
if (!$result2)  die("no data to treat");
$now=time();
while($row=pg_fetch_assoc($result2)) {
    $courseid=$row['courseid'];
    $sql3 ="SELECT COUNT(DISTINCT(u.id)) AS nbpa
FROM mdl_user u
INNER JOIN mdl_user_enrolments ue ON ue.userid = u.id
INNER JOIN mdl_enrol e ON e.id = ue.enrolid
INNER JOIN mdl_role_assignments ra ON ra.userid = u.id
INNER JOIN mdl_context ct ON ct.id = ra.contextid 
     AND ct.contextlevel = 50
INNER JOIN mdl_course c ON c.id = ct.instanceid 
     AND e.courseid = c.id
INNER JOIN mdl_role r ON r.id = ra.roleid 
     AND r.shortname = 'student'
WHERE e.status = 0 AND u.suspended = 0 AND u.deleted = 0 AND (ue.timeend = 0 OR ue.timeend > $now) 
AND ue.status = 0 AND c.id = $courseid";
     $result3 = pg_query($connexion,$sql3);
     if ($result3==false) continue;
     $row=pg_fetch_assoc($result3);
     $nbpa=$row['nbpa'];
     $sql4="INSERT INTO temp_logstore_socialflow_nbpa (courseid, nbpa) VALUES ($courseid,$nbpa)";
     $result4 = pg_query($connexion,$sql4);
     if ($result4==false) continue;   
 }
 /* Comme la syntaxe pour faire un RENAME varie entre Posqresql et Mysql, j'utilise truncate et je remplace le contenu de la table, dans moodle, je pourrais utiliser les fonction rename_table(anciennom, nouveaunom)  et drop_table d'apès ce que je trouve dans lib/ddl/database_manager.php mais je préfère pouvoir faire la requête en une seule ligne qui passe ou qui ne passe pas'*/
$sql5="TRUNCATE TABLE mdl_logstore_socialflow_nbpa; INSERT INTO mdl_logstore_socialflow_nbpa SELECT * FROM temp_logstore_socialflow_nbpa";
$result5 = pg_query($connexion,$sql5);
if ($result5==false) die("unable to rename tables");   
$sql6="DROP TABLE temp_logstore_socialflow_nbpa"; 
$result6 = pg_query($connexion,$sql6);
if ($result6==false) die("unable to drop temp table");   
 
pg_close($connexion);

Temps d’exécution de ce script : 5 minutes ! C’est méga efficace et ça va soulager toutes mes requêtes de flux social !

Temps de travail sur ce script et cet article : 1/2 jour