perf: replace fat-view student index query with lean getPublishedAuthors()

The répertoire page was loading the full v_theses_public view
(15 JOINs + 8 GROUP_CONCAT temp B-trees) via getAllPublishedTheses()
just to build the student name → thesis-id map on the index page.
Only two columns (id, authors) were ever consumed by the template.

Add Database::getPublishedAuthors(): array
- Queries thesis_authors JOIN authors directly on the theses base table
- Filters on theses.is_published = 1 using the existing index
- Returns only id + GROUP_CONCAT(authors) — no view expansion
- Results verified identical to the old getAllPublishedTheses() output

Update search.php to call getPublishedAuthors() instead.
Mark getAllPublishedTheses() @deprecated in Database.php.

All tests pass.
This commit is contained in:
Pontoporeia
2026-03-28 13:35:43 +01:00
parent 1181cfa88b
commit 7d96a08324
5 changed files with 34 additions and 8 deletions

View File

@@ -408,6 +408,10 @@ class Database {
/**
* Return ALL published theses (no cap) — for internal use (student index).
* Not exposed to user-controlled input.
*
* @deprecated Use getPublishedAuthors() for the répertoire student index —
* it avoids the expensive v_theses_public view and only fetches
* the two columns actually needed (id, authors).
*/
public function getAllPublishedTheses(): array {
$stmt = $this->pdo->query(
@@ -416,6 +420,29 @@ class Database {
return $stmt->fetchAll();
}
/**
* Lean query for the répertoire student-name index.
*
* Avoids the fat v_theses_public view (15 JOINs + 8 GROUP_CONCAT B-trees).
* Queries thesis_authors → authors directly, letting the index on
* theses(is_published) filter the base table before any JOIN.
*
* Returns rows of [id => int, authors => "Name1,Name2"].
*/
public function getPublishedAuthors(): array {
$stmt = $this->pdo->query(
"SELECT t.id,
GROUP_CONCAT(a.name ORDER BY ta.author_order ASC) AS authors
FROM theses t
JOIN thesis_authors ta ON ta.thesis_id = t.id
JOIN authors a ON a.id = ta.author_id
WHERE t.is_published = 1
GROUP BY t.id
ORDER BY MIN(a.name) ASC"
);
return $stmt->fetchAll();
}
public function getAvailableYears() {
$sql = "SELECT DISTINCT year FROM theses WHERE is_published = 1 ORDER BY year DESC";
$stmt = $this->pdo->query($sql);