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

@@ -363,12 +363,11 @@ Goal: rename the tables and column to the canonical M2M pattern (`tags`, `thesis
with a plain table query in `searchTheses` and `getPublishedTheses`** — build the minimal JOIN set
per query and let indexes filter `theses` first. Keep the views for reporting/admin use only.
- [ ] **`getAllPublishedTheses()` in `search.php`** — fetches every published thesis (all columns,
- [x] **`getAllPublishedTheses()` in `search.php`** — fetches every published thesis (all columns,
all JOINs) just to build the student-name index on the Répertoire page. This is a full table
scan through the fat view. Replace with a dedicated lean query:
`SELECT id, authors FROM v_theses_public ORDER BY authors ASC` — or add
`Database::getPublishedAuthors(): array` that queries `thesis_authors JOIN authors` directly,
avoiding the view entirely.
scan through the fat view. Replaced with `Database::getPublishedAuthors(): array` that queries
`thesis_authors JOIN authors` directly (only `id` + `authors` columns), avoiding the view entirely.
`getAllPublishedTheses()` kept but marked `@deprecated`.
- [x] **`migration 005` view is stale in the file** — `005_add_banner.sql` recreates the view still
referencing `thesis_keywords` / `keywords.keyword` (the old pre-migration-001 names).

View File

@@ -46,8 +46,8 @@ try {
$orientations = $db->getAllOrientations();
$apPrograms = $db->getAllAPPrograms();
$keywords = $db->getUsedTags();
// Fetch all published theses for the student index (no artificial cap)
$students = $db->getAllPublishedTheses();
// Fetch id+authors only — lean query bypassing the fat v_theses_public view
$students = $db->getPublishedAuthors();
} catch (InvalidArgumentException $e) {
$validationError = $e->getMessage();
$results = []; $totalItems = 0; $totalPages = 0;

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);

View File

@@ -1 +1 @@
[1774694544]
[1774701325]

Binary file not shown.