Requete trop trop lente sous Postgres - SQL/NoSQL - Programmation
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?
(c'est une remarque stérile je suis d'accord mais c'est un départ)
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.
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.
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.
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...
Marsh Posté le 30-10-2003 à 23:51:40
y'a des index sur les champs sur lequels tu fais les min et max?
Marsh Posté le 31-10-2003 à 00:04:34
Essaie de voir du côté de ça :
|
=> Ca marche sous Oracle, mais pas sous Access, sous Ingres chais pas, c'est entre les deux
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
Marsh Posté le 31-10-2003 à 00:07:12
ReplyMarsh 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
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.
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
Marsh Posté le 31-10-2003 à 09:37:35
En tout cas, le MagicBuzz il est bleuffed.
|
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 )
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
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.
Marsh Posté le 31-10-2003 à 09:44:25
Reply
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.