2011-01-07 6 views
0

C'est ma requête en cours, cela fonctionne, mais il est lent:Optimisation des requêtes

SELECT row, MIN(flg) ||' to ' ||Max (flg) as xyz , avg(amt_won), count(*) 
FROM(
SELECT (ROW_NUMBER() OVER (ORDER BY flg))*100/ 
(SELECT count(*)+100 as temprow FROM temporary_six_max) as row, flg, amt_won 
FROM temporary_six_max 
    JOIN (
    SELECT id_player AS pid, avg(flg_vpip::int) AS flg 
    FROM temporary_six_max 
    GROUP BY id_player 
    ) AS auxtable 
    ON pid = id_player 
) as auxtable2 
group by 1 
order by 1; 

je groupe en fixe (ou presque fixe) compte 100 plages qui sont commandés par avg (flg_vpip) regroupés par id_player.

Ici, j'ai collé les résultats dans le cas où il peut aider à comprendre: https://spreadsheets0.google.com/ccc?key=tFVsxkWVn4fMWYBxxGYokwQ&authkey=CNDvuOcG&authkey=CNDvuOcG#gid=0

Je me demande s'il y a une meilleure fonction à utiliser que ROW_NUMBER() dans ce cas et je me sens comme je le fais aussi beaucoup de sous-sélection mais je ne sais pas comment l'optimiser.

J'apprécierai beaucoup toute aide.

Si quelque chose n'est pas clair, faites le moi savoir.

Merci.

EDIT:

Si je créé auxtable 2, est que lors de l'utilisation (ROW_NUMBER() OVER (ORDER BY FLG), et utiliser d'autres commandes d'agrégat tel que le moyen (amt_won) et count (*), qui sont essentiels, je reçois une erreur disant que FLG devrait être dans la fonction d'agrégation, mais je ne peux pas commander par une fonction d'agrégation de FLG

+1

Veuillez aussi publier la sortie de EXPLAIN ANALYZE. Et s'il vous plaît expliquer ce que vous essayez de réaliser avec les sélections imbriquées (je veux dire * auxtable4 * pas la table dérivée * auxtable2 * Actuellement je ne comprends pas le but de cela –

+0

J'ai posté l'ANALYZE EXPLAIN dans le gdocs sur le lien ci-dessus Merci pour la création de auxtable4 et auxtable 2. Merci – joaoavf

+1

'max (row_number())' est essentiellement 'count (*) over (...)', mais je ne comprends toujours pas les calculs que vous faites à cela (divisant et le +100) .Mais je comprends l'intention maintenant –

Répondre

2

I généré des données à tester avec comme ceci:.

create table temporary_six_max as 
select id_player, flg_vpip, 
     random()*100 * (case flg_vpip when 0 then 1 else -1 end) as amt_won 
from (select (random()*1000)::int as id_player, random()::int as flg_vpip 
     from generate_series(1,1000000)) source; 
create index on temporary_six_max(id_player); 

Votre requête s'exécute avec succès contre cela, mais ne génère pas tout à fait le même plan, je reçois une boucle imbriquée dans le bras inférieur plutôt qu'une fusion et une analyse seq dans le plan d'initialisation - vous n'avez pas désactivé enable_seqscan j'espère?

Une solution juste en utilisant un seul balayage de la table:

select row, min(flg) || ' to ' || max(flg) as xyz, avg(amt_won), count(*) 
from (select flg, amt_won, ntile(100) over(order by flg) as row 
     from (select id_player as pid, amt_won, 
        avg(flg_vpip::int) over (partition by id_player) as flg 
      from temporary_six_max 
      ) player_stats 
    ) chunks 
group by 1 
order by 1 

Les mauvaises nouvelles sont que cela joue en fait pire sur ma machine, surtout si je bosse work_mem assez pour éviter le premier type de disque (en créant player_stats, en triant par flg). Bien que l'augmentation de work_mem réduise de moitié le temps de la requête, donc je suppose que c'est au moins un début? Cela dit, mes requêtes sont en cours d'exécution pendant environ 5 secondes pour traiter 10E6 lignes d'entrée dans temporary_six_max, ce qui est un ordre de grandeur plus rapide que vous avez posté. Votre table s'intègre-t-elle dans votre cache tampon? Si ce n'est pas le cas, une solution de numérisation unique peut être bien meilleure pour vous. (Quelle version de Postgresql utilisez-vous? "Expliquer (analyser sur, tampons sur) sélectionner ..." vous montrera les taux de succès/échec du tampon dans 9.0, ou regardez simplement votre paramètre "shared_buffers" et comparez avec la taille de la table)