Mini Projet — Optimisation Oracle

Base de données NBA 2023/24
Analyse et optimisation SQL

Analyse des plans d'exécution, création d'index B-tree, mesure de l'impact sur les performances.

Module : BDD OGA Niveau : Ingénieur 3ème année SGBD : Oracle XE 21c Présentation : 03/05/2026
Requêtes analysées
5
avec EXPLAIN PLAN
Index créés (total)
9
B-tree — R1 à R5
Meilleur gain
−91%
consistent gets R3 : 265 → 24
Requêtes optimisées
5 / 5
index range scan actif

Requêtes SQL

1
Joueurs ayant réalisé un triple double — saison 2023/24
✓ Optimisée

Détecte les joueurs ayant au moins 3 catégories statistiques ≥ 10 dans un même match (points, rebonds, passes, interceptions, contres).

SELECT
    p.first_name || ' ' || p.last_name  AS joueur,
    g.game_date                          AS date_match,
    g.season                             AS saison,
    gs.points                            AS pts,
    gs.rebounds                          AS reb,
    gs.assists                           AS ast,
    gs.steals                            AS stl,
    gs.blocks                            AS blk
FROM game_stats gs
JOIN players p ON gs.player_id = p.player_id
JOIN games   g ON gs.game_id   = g.game_id
WHERE g.season = '2023-24'
  AND (
        (CASE WHEN gs.points   >= 10 THEN 1 ELSE 0 END)
      + (CASE WHEN gs.rebounds >= 10 THEN 1 ELSE 0 END)
      + (CASE WHEN gs.assists  >= 10 THEN 1 ELSE 0 END)
      + (CASE WHEN gs.steals   >= 10 THEN 1 ELSE 0 END)
      + (CASE WHEN gs.blocks   >= 10 THEN 1 ELSE 0 END)
      ) >= 3
ORDER BY g.game_date, joueur;

Résultat obtenu

1 ligne retournée
Nikola Jokic 24/10/2023 29 pts 13 reb 11 ast 2 stl · 1 blk

Comparaison des plans d'exécution

✗ AVANT index — consistent gets : 28 — 1.105s
Plan hash: 2093995845

|* 5 | TABLE ACCESS FULL    | GAME_STATS  |
|  6 | TABLE ACCESS BY ROWID| PLAYERS     |
|* 7 |  INDEX UNIQUE SCAN   | SYS_C008272 |
|* 8 | INDEX UNIQUE SCAN    | SYS_C008278 |
|* 9 | TABLE ACCESS BY ROWID| GAMES       |

Problème : full scan GAME_STATS (40 lignes)
Filtre season appliqué APRÈS le scan complet
✓ APRÈS index — consistent gets : 6 — 0.500s
Plan hash: 2205428426

|  6 | INDEX FULL SCAN      | IDX_GS_GAME_ID   |
|* 9 | INDEX RANGE SCAN     | IDX_GAMES_SEASON |
|*10 | INDEX UNIQUE SCAN    | SYS_C008272      |
|* 5 | TABLE ACCESS BY ROWID| GAME_STATS       |
| 11 | TABLE ACCESS BY ROWID| PLAYERS          |

IDX_GAMES_SEASON filtre la saison EN PREMIER
→ Élimination du full scan sur GAME_STATS

Gains mesurés

Gets avant28
Gets après6
Réduction gets−78%
Temps avant1.105s
Temps après0.500s
Réduction temps−55%
2
Joueurs de plus de 2m ayant fait des interceptions
✓ Optimisée

Retourne les joueurs de taille ≥ 79 pouces (2m) ayant réalisé au moins une interception, avec le nombre de matchs concernés.

SELECT DISTINCT
    p.first_name || ' ' || p.last_name  AS joueur,
    p.height_inches                      AS taille_pouces,
    ROUND(p.height_inches * 2.54, 1)    AS taille_cm,
    COUNT(DISTINCT gs.game_id)           AS nb_matchs
FROM players p
JOIN game_stats gs ON p.player_id = gs.player_id
WHERE p.height_inches >= 79
  AND gs.steals > 0
GROUP BY p.first_name, p.last_name, p.height_inches
ORDER BY p.height_inches DESC;

Résultat obtenu

9 lignes retournées
Chet Holmgren 85 pouces (215,9 cm) Giannis 83 pouces (210,8 cm) Nikola Jokic 83 pouces (210,8 cm) + 6 autres joueurs

Comparaison des plans d'exécution

✗ AVANT index — consistent gets : 14 — 0.057s
TABLE ACCESS FULL sur PLAYERS
TABLE ACCESS FULL sur GAME_STATS
2 table scans (short tables)
Filtre height_inches appliqué après scan complet
✓ APRÈS index — consistent gets : 4 — 0.055s
2 index range scans actifs
idx_players_height → filtre >= 79 direct
idx_gs_steals → filtre steals > 0 direct
idx_gs_player_id → jointure accélérée
Gets avant14
Gets après4
Réduction gets−71%
Temps avant0.057s
Temps après0.055s
3
Total des rebonds — Golden State Warriors
✓ Optimisée

Calcule la somme des rebonds pris par tous les joueurs de Golden State sur la saison 2023-24.

SELECT
    t.city || ' ' || t.team_name    AS equipe,
    g.season                         AS saison,
    SUM(gs.rebounds)                 AS total_rebonds
FROM teams t
JOIN players   p  ON p.team_id    = t.team_id
JOIN game_stats gs ON gs.player_id = p.player_id
JOIN games     g  ON gs.game_id   = g.game_id
WHERE t.city = 'Golden State'
  AND g.season = '2023-24'
GROUP BY t.city, t.team_name, g.season;

Résultat obtenu

1 ligne retournée
Golden State Warriors Saison 2023-24 Total rebonds : 24

Comparaison des plans d'exécution

✗ AVANT index — consistent gets : 265 — 0.125s
15 table scans (short tables)
TABLE ACCESS FULL sur TEAMS, GAMES, GAME_STATS
Filtre city et season appliqués après scans complets
265 blocs lus en mémoire
✓ APRÈS index — consistent gets : 24 — 0.044s
3 index range scans actifs
idx_teams_city → filtre city direct
idx_games_season → filtre saison direct
idx_gs_player_game → jointure couverte
−91% de blocs lus
Gets avant265
Gets après24
Réduction gets−91%
Temps avant0.125s
Temps après0.044s
Réduction temps−65%
4
Maximum de points dans un seul match
✓ Optimisée

Trouve le joueur ayant marqué le plus de points dans un seul match, toutes saisons confondues.

SELECT
    p.first_name || ' ' || p.last_name  AS joueur,
    g.game_date                          AS date_match,
    gs.points                            AS points_max
FROM game_stats gs
JOIN players p ON gs.player_id = p.player_id
JOIN games   g ON gs.game_id   = g.game_id
WHERE gs.points = (
    SELECT MAX(points) FROM game_stats
)
ORDER BY g.game_date;

Résultat obtenu

1 ligne retournée
Giannis Antetokounmpo 31/10/2023 38 points

Comparaison des plans d'exécution

✗ AVANT index — consistent gets : 44 — 0.093s
TABLE ACCESS FULL sur GAME_STATS (x2)
Sous-requête MAX(points) scan complet
3 table scans (short tables)
44 blocs lus en mémoire
✓ APRÈS index — consistent gets : 18 — 0.032s
idx_gs_points → MAX() par lecture feuille B-tree
INDEX FETCH BY KEY pour la valeur max
Sous-requête résolue sans scan complet
−59% de blocs lus
Gets avant44
Gets après18
Réduction gets−59%
Temps avant0.093s
Temps après0.032s
Réduction temps−66%
5
Joueur avec le plus de points — saison 2023/24
✓ Optimisée

Trouve le joueur ayant cumulé le plus grand nombre de points sur l'ensemble de la saison 2023-24.

SELECT
    p.first_name || ' ' || p.last_name  AS joueur,
    g.season                             AS saison,
    SUM(gs.points)                       AS total_points
FROM game_stats gs
JOIN players p ON gs.player_id = p.player_id
JOIN games   g ON gs.game_id   = g.game_id
WHERE g.season = '2023-24'
GROUP BY p.first_name, p.last_name, g.season
HAVING SUM(gs.points) = (
    SELECT MAX(SUM(gs2.points))
    FROM game_stats gs2
    JOIN games g2 ON gs2.game_id = g2.game_id
    WHERE g2.season = '2023-24'
    GROUP BY gs2.player_id
)
ORDER BY total_points DESC;

Résultat obtenu

1 ligne retournée
Giannis Antetokounmpo Saison 2023-24 Total : 72 pts

Comparaison des plans d'exécution

✗ AVANT index — consistent gets : 62 — 0.070s
6 table scans (short tables)
Sous-requête MAX(SUM()) sans index
TABLE ACCESS FULL sur GAME_STATS (x2)
62 blocs lus en mémoire
✓ APRÈS index — consistent gets : 48 — 0.061s
2 index range scans actifs
idx_games_season → filtre saison direct
idx_gs_gameid_player_points → couvre JOIN + SUM
INDEX FETCH BY KEY pour la sous-requête
−23% de blocs lus
Gets avant62
Gets après48
Réduction gets−23%
Temps avant0.070s
Temps après0.061s
Réduction temps−13%

Index créés

Nom de l'indexTableColonnes TypeRequêteJustification
idx_games_season games season B-tree R1 INDEX RANGE SCAN sur la saison — filtre les matchs avant de joindre game_stats
idx_gs_game_id game_stats game_id B-tree R1 Élimine le TABLE ACCESS FULL — permet le MERGE JOIN via l'index
idx_gs_player_id game_stats player_id B-tree R1 Optimise la jointure game_stats → players
idx_players_height players height_inches B-tree R2 INDEX RANGE SCAN sur height ≥ 79 — évite TABLE ACCESS FULL sur PLAYERS
idx_gs_steals game_stats steals B-tree R2 Filtre steals > 0 sans scan complet de GAME_STATS
idx_teams_city teams city B-tree R3 Accès direct à 'Golden State' sans parcourir toute la table TEAMS
idx_games_season games season B-tree R3, R5 Filtre saison '2023-24' en amont — réutilisé par R5
idx_gs_player_game game_stats player_id, game_id Composite R3 Couvre les deux jointures player et game simultanément
idx_gs_points game_stats points B-tree R4 MAX(points) résolu par lecture de la feuille droite du B-tree en O(log n)
idx_gs_gameid_player_points game_stats game_id, player_id, points Composite R5 Couvre jointure + GROUP BY + SUM(points) — index de couverture

Comparaison des performances

Métrique : consistent gets issue de SET AUTOTRACE ON. Plus la valeur est basse, moins Oracle lit de blocs en mémoire.

Bilan d'optimisation

TABLE ACCESS FULL éliminé sur GAME_STATS (R1)

Oracle lisait les 40 lignes sans index. Après, il utilise IDX_GS_GAME_ID (INDEX FULL SCAN) combiné à IDX_GAMES_SEASON (INDEX RANGE SCAN) via un MERGE JOIN.

R2 — −71% consistent gets (14 → 4) grâce aux index sur height et steals

Les filtres height_inches ≥ 79 et steals > 0 utilisent désormais des INDEX RANGE SCAN au lieu de TABLE ACCESS FULL.

R3 — Meilleur résultat : −91% consistent gets (265 → 24) · −65% temps

La combinaison idx_teams_city + idx_games_season + idx_gs_player_game couvre les 4 tables de la jointure. Oracle filtre Golden State et la saison en premier, réduisant massivement le volume traité.

R4 — −59% consistent gets (44 → 18) · −66% temps grâce à idx_gs_points

Le MAX(points) est résolu par lecture directe de la feuille droite du B-tree en O(log n) au lieu d'un scan complet de la table.

R5 — −23% consistent gets (62 → 48) grâce à l'index composite de couverture

L'index idx_gs_gameid_player_points couvre la jointure, le GROUP BY et le SUM(points) en un seul accès. La sous-requête MAX(SUM()) bénéficie aussi de idx_games_season.

Inconvénient : coût de maintenance des 9 index créés

Tout INSERT dans game_stats, games, players ou teams met à jour les index correspondants. Sur de petites tables l'impact est négligeable, mais sur des millions de lignes il faut désactiver les index pendant les chargements massifs (ALTER INDEX ... UNUSABLE).

Équipe projet

SI

Sahi Nour El Imene

Setup Oracle · Import BD NBA · Requête 1 (triple double)

ML

Maouche Lina

Requêtes 2, 3, 4, 5 · Plans d'exécution · Index