2013-04-27 5 views
-1

Disons que j'ai un schéma de base de données Oracle comme ceci:
tournois (id, nom) joueurs (id, nom) gameinfo (id, pid (références players.id), tid (références tournaments.id), date)
Ainsi, une rangée dans la table gameinfo signifie qu'un certain joueur a joué un certain jeu dans un tournoi à une date donnée. Les tournois ont environ 20 records, les joueurs environ 160 000 et les informations de jeu environ 2 millions. Je dois écrire une requête qui répertorie les tournois (avec TID dans la plage de 1-4) et le nombre de joueurs qui ont joué leur premier match dans ce tournoi.
je suis venu avec la requête suivante:Optimisation des requêtes dans Oracle SQL

select tid, count(pid)
from gameinfo g
where g.date = (select min(date) from gameinfo g1 where g1.player = g.player)
and g.tid in (1,2,3,4) group by tid;

Ceci est clairement suboptimale (il a couru pendant environ 58 minutes). J'ai eu une autre idée, que je pouvais faire une vue:

select pid, tid, min(date)
from gameinfo
where tid in(1,2,3,4)
group by pid, tid;

Et exécuter mes requêtes sur ce point de vue, car il ne comptait environ 600 000 dossiers, mais cela semble encore moins optimale.

Pouvez-vous donner des conseils sur la façon dont cela pourrait être optimisé?

+0

Quel est le plan d'explication de la requête? Est-ce que les tableaux ont des statistiques? Il n'y a rien nécessairement faux avec la requête elle-même. –

Répondre

5

Ma première recommandation est d'essayer d'abord les fonctions analytiques. La fonction row_number() énumérera les tournois pour chaque utilisateur. Le premier a une seqnum de 1:

select gi.* 
from (select gi.*, 
      row_number() over (partition by gi.player order by date) as seqnum 
     from gameinfo gi 
    ) gi 
where tid in(1,2,3,4) and seqnum = 1 

Ma deuxième suggestion est de mettre la date du premier tournoi dans la table players, car il semble que des informations importantes pour l'utilisation de la base de données.