Requete trop trop lente sous Postgres

Requete trop trop lente sous Postgres - SQL/NoSQL - Programmation

Marsh Posté le 30-10-2003 à 15:26:36    

Salut,  
 
j'ai créé la vue ci-dessous sous Postgresql. J'ai créé des index sur les différents id. Il y a environ 2500 enregistrements dans la table demande (autrement dit rien).  
Si je fais un select count(*) de la vue ça prend 10 s. je pige pas pourquoi.  
 
Merci de vos conseils.  
 
Nestor.
 
CREATE VIEW gestion AS
 SELECT demande.id_demande,  
 demande.id_service,  
 demande.objet,  
 demande.date_debut_demande,  
 etape.id_etape,  
 etape.date_etape,  
 procedures.libelle_procedure,  
 version,  
 environnement,  
 demande.id_demandeur,  
 demande.fin,  
 etape.id_procedure,  
 demande.id_version,  
 service.no_compte,  
 etape.id_responsable,  
 item_etape.id_actioneur  
 FROM demande,etape,procedures,version,service,item_etape  
 WHERE demande.id_demande = etape.id_demande  
 AND etape.id_etape = (SELECT max(id_etape) FROM etape WHERE demande.id_demande = etape.id_demande)  
 AND item_etape.id_item = (SELECT MIN(id_item) FROM item_etape WHERE item_etape.id_etape = etape.id_etape)  
 AND etape.id_procedure = procedures.id_procedure  
 AND demande.id_version = version.id_version  
 AND service.id_service = demande.id_service  
UNION  
 SELECT demande.id_demande,  
 demande.id_service,  
 demande.objet,  
 demande.date_debut_demande,  
 null,  
 null,  
 null,  
 version,  
 environnement,  
 demande.id_demandeur,  
 demande.fin,  
 null,  
 demande.id_version,  
 service.no_compte,  
 null,  
 null  
 FROM demande,version,service  
 WHERE demande.id_demande  
 NOT IN (SELECT etape.id_demande FROM etape)  
 AND demande.id_version = version.id_version  
 AND service.id_service = demande.id_service;
 
En fait je veux toutes les demandes avec leur dernière étape (s'il y en a une) et le premier item de l'étape.

Reply

Marsh Posté le 30-10-2003 à 15:26:36   

Reply

Marsh Posté le 30-10-2003 à 18:30:07    

Nestor a écrit :

Si je fais un select count(*) de la vue ça prend 10 s. je pige pas pourquoi.  


 
euh t'as vu la tronche de ta vue? [:mlc]
(c'est une remarque stérile je suis d'accord mais c'est un départ)


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 30-10-2003 à 19:41:01    

Ouais bof, moi je ne trouve pas que ce soit énorme comme vue (elle est surtout longue car je ramène pas mal de champs mais il n'y a jamais que 6 tables).  
 
T'es pas gentil avec moi mais ça au moins le mérite de remonter mon post...
 
Nestor.

Reply

Marsh Posté le 30-10-2003 à 19:52:15    

chelou. en effet elle a rien d'extraordinaire cette vue.
 
tu peux virer le UNION et refaire le test avec seulement la première partie, puis seulement la seconde ?
 
juste histoire de voir quelle partie de la vue est si lente.

Reply

Marsh Posté le 30-10-2003 à 22:27:06    

MagicBuzz tu as eu une excellente idée de me faire faire ça : en effet, pour moi il était évident que c'est la première partie qui est lente et pas du tout : c'est la deuxième !!
 
Il n'aime pas le 'NOT IN' à priori.  
 
Bon, je n'ai pas encore la solution mais peut-être que je suis déjà plus dans la bonne direction.  
Ceci dit, je suis preneur d'autres idées !
 
Merci.
Nestor.

Reply

Marsh Posté le 30-10-2003 à 23:41:04    

J'ai en effet pensé aussi au NOT IN dès le départ, mais la requête est tellement simple que je ne pensais pas que ce soit à ce point.
Mais en effet, le NOT IN est réputépour être une instruction extrêment lente.
 
Pour ce qui est d'une solution, je n'ai de solution à te proposer à froid...
 
Faudrait que tu m'expliques un peu plus ton modèle des données, parfois on peut éviter un union en faisant un truc très simple... ou alors complexifier à mort une requête et au final avoir pourtant des performances accrues. Tout dépend du modèle et de ce que tu veux récupérer...

Reply

Marsh Posté le 30-10-2003 à 23:51:40    

y'a des index sur les champs sur lequels tu fais les min et max?


---------------
Hey toi, tu veux acheter des minifigurines Lego, non ?
Reply

Marsh Posté le 31-10-2003 à 00:04:34    

Essaie de voir du côté de ça :
 


SELECT * from a
minus
select * from b


 
=> Ca marche sous Oracle, mais pas sous Access, sous Ingres chais pas, c'est entre les deux :D
 
MINUS fait comme un UNION sauf qu'il va retourner toutes les lignes de A qui ne sont pas présentes dans B. En bidouillant bien, ça te permettra peut-être de virer le NOT IN (à la base, c'est ce que tu fais). Par contre, je ne sais pas niveau perf ce que vaut le MINUS, personne ne l'utilise jamais...
 
Regarde ce cours (format PPT) pour avoir plus d'explications sur le fonctionnement des différents mots-clés qui s'offrent à toi.
http://www.unibz.it/web4archiv/obj [...] -query.ppt


Message édité par MagicBuzz le 31-10-2003 à 00:06:42
Reply

Marsh Posté le 31-10-2003 à 00:07:12    

%20 [:kiki]


---------------
Hey toi, tu veux acheter des minifigurines Lego, non ?
Reply

Marsh Posté le 31-10-2003 à 00:09:21    


ouais mais ça marchais pas de toute façon, parceque je m'étais planté de lien, du coup j'ai remis le bon lien et hô miracle ça marche :D

Reply

Marsh Posté le 31-10-2003 à 00:09:21   

Reply

Marsh Posté le 31-10-2003 à 08:25:47    

Nan mais en fait, je vais pas me faire ch???? : je vais ajouter un champ boolean dans la table demande qui aura 0 s'il n'y a pas d'étape et 1 s'il y en a.  
Ensuite je fais une requete de mise à jour de ce champs pour les données existantes.  
Enfin je fais un triger pour mettre à jour ce champ chaque fois que je fais une étape.  
 
Et je n'ai pas plus qu'à modifier la deuxième partie de ma requète UNION en disant que je veux les demandes where mon nouveau champ = false.  
 
Pour Real moins moins : oui il y a les index qui vont bien.  
 
Magic : j'avais pensé à faire un "minus" mais comme je peux sans problème mettre en place la modif que je décris ici, autant ne pas le faire.
 
Merci pour tout.  
Nestor.


Message édité par Nestor le 31-10-2003 à 08:27:28
Reply

Marsh Posté le 31-10-2003 à 09:27:54    

c'est clair que si tu peux modifier les tables, la question se pose même pas :)
 
moi j'ai tellement l'habitude de bosser avec des modèles mals conçus et que je ne peux pas faire évoluer que je pense même plus à modifier, je cherche à pallier au problème avec les moyens du bords :D

Reply

Marsh Posté le 31-10-2003 à 09:37:35    

En tout cas, le MagicBuzz il est bleuffed.
 


select * from tie where codsoc = 0
minus
select * from tie where codsoc = 0 and typtie = 'CLI' and nomtie like 'GEMS%'


 
TIE est une table contenant 49011 lignes et... 139 colonnes, toutes ou presque sont des varchar2(12) (ça c'est un modèle bien conçu encore :D)
 
La requête ci-dessus récupère tous les tiers, sauf les 100 clients dont le nom commence par 'GEMS'.
 
Premier membre de la requête : 93 ms
Second membre de la requête : 234 ms
 
La requête complète : 4 secondes
 
Pour comparaison, un union dure 9 secondes (sisi) tandis qu'un union all dure 125 ms et un intersect dure 8 secondes.
 
Donc tu peux y aller à coup de minus ça semble assez profitable :)


Message édité par MagicBuzz le 31-10-2003 à 09:42:52
Reply

Marsh Posté le 31-10-2003 à 09:42:28    

Tu as testé ça avec quel SGBD ?  
 
Sinon, oui je peux à peu près faire ce que je veux avec la base, il faut juste que je respecte l'existant.  
 
 
Je te remercie de ton intérêt en tout cas !
 
Nestor.

Reply

Marsh Posté le 31-10-2003 à 09:44:25    

Nestor a écrit :

Tu as testé ça avec quel SGBD ?  


Arf, j'ai oublié de préciser ;)
 
Oracle 8i sous Unix

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed