[SGBD] Décrotter une requête

Décrotter une requête [SGBD] - SQL/NoSQL - Programmation

Marsh Posté le 26-07-2004 à 12:19:15    

Je suis en train de faire un moteur de recherche pour un site. Et vu que j'ai bien la tête dans le c*l ce matin, j'ai l'impression que la requête aurait pu être un peu mieu...
 
SDBG : Oracle 8i (bientôt 9i)
Tout d'abord, voici le modèle des données (mais nan, n'ayez pas peur :ange:) :
http://perso.wanadoo.fr/magicbuzz/mpd_cms.png
 
Pour résumer :
-> Les produits (référence) sont stockés dans la table PRO.
-> Les noms et descriptions des produits sont stockés dans la table PRM.
-> Si un produit n'est pas traduit dans la langue du client, alors on recherche aussi dans la langue anglaise.
-> Un client (sigtie) peut avoir des codes personnalisés pour chacun des produits (table PROTIE)
-> Une version évoluée de la fiche produit peut être présente dans la table NEWS. Dans ce cas, on recherche la "news" qui est dans la langue du produit PRM trouvé (langue du client ou anglais si langue du client pas trouvée)
-> Chaque "news" peut contenir des documents dans la table MED
 
PS: le modèle des données n'est pas tout à fait à jour, il n'est là que pour voir la structure des données, les champs on légèrement évolué.
 
La recherche doit se faire sur tous les "codes" du produit (code client, interne et fournisseur), les différents libélls et les noms des documents associés.
 
Voici la requête que j'ai pondu :


select codpro
from
(
 select allpro.codsoc, allpro.codpro, allpro.codpro || allpro.motcle || allpro.refpro || allpro.nompro || news.header || news.desc1 || news.desc2 || news.desc3 || news.desc4 || news.desc5 || med.title || med.path || allpro.codprotie keywords  
 from med, news,  
  (
  select pro.codsoc, pro.codpro, pro.motcle, pro.refpro, nvl(lng.codlan, eng.codlan) codlan, nvl(lng.nompro || lng.txtpro, eng.nompro || eng.txtpro) nompro, protie.codprotie
  from protie, prm eng, prm lng, pro
  where lng.codsoc(+) = pro.codsoc
  and lng.codpro(+) = pro.codpro
  and lng.codlan(+) = 'FRA'
  and eng.codsoc = pro.codsoc
  and eng.codpro = pro.codpro
  and eng.codlan = 'ENG'
  and protie.codsoc(+) = pro.codsoc
  and protie.sigtie(+) = '520036'
  and protie.codpro(+) = pro.codpro
  ) allpro
 where news.codsoc(+) = allpro.codsoc
 and news.typnew(+) = 'PRO'
 and news.codlan(+) = allpro.codlan
 and news.codpro(+) = allpro.codpro
 and med.codsoc(+) = allpro.codsoc
 and med.tabori(+) = 'PRO'
 and med.cle1(+) = allpro.codpro
 and med.typtie(+) = 'PRO'
 and med.codlan(+) = allpro.codlan
) search
where search.codsoc = 0
and upper(search.keywords) like upper('%papier%')


 
=> Ici, le client francophone d'id 520036 recherche un produit en utilisant le mot-clé "papier"
 
La requête tourne bien, et retourne le résultat attendu en 31 ms (219 ms lorsque la requête n'est pas en cache).
Seulement, actuellement j'ai pas beaucoup de lignes :
 
PRO : 32
PRM : 63
NEWS : 36
MED : 48
PROTIE : 1
 
Dans le futur, je pense avoir ca à peut près :
PRO : 30 000
PRM : PRO * 5 = 150 000
NEWS : PRO * 6 = 180 000
MED : NEWS * 3 = 540 000
PROTIE : 50 000 / 100 * 10 = 5 000
 
C'est pas vraiment la même donne...
Deplus, actuellement, je n'ai qu'un mot clé, à l'avenir, il y en aura certainement beaucoup plus.
 
J'ai écrit cette requête de cette façon plutôt que faire un like sur chaque champ, afin de pouvoir la rendre facilement évolutive, notamment la partie dynamique (ajout de mots clés et de critères de recherche).


Message édité par Arjuna le 26-07-2004 à 12:19:52
Reply

Marsh Posté le 26-07-2004 à 12:19:15   

Reply

Marsh Posté le 26-07-2004 à 12:46:49    

euh... question bête, ton search.codesoc=0, il vient d'où? C'est un critère de recherche ou une constante?

Reply

Marsh Posté le 26-07-2004 à 14:02:15    

Constante, mais que je dois conserver au plus haut niveau possible, car il sera d'ici 1 an environ dynamique (gestion multi-société de l'ERP)
 
Il est propagé depuis la sous-sous-requête, sur la table pro, et utilisé pour les jointures avec toutes les autres tables.
 
A noter que je le sors au maximum, car il y a de fortes chances pour que je passe cette requête en vue si ça rame trop.


Message édité par Arjuna le 26-07-2004 à 14:02:58
Reply

Marsh Posté le 26-07-2004 à 14:38:58    

mouais, chuis pas convaincu. A mon avis, même en variable, tu peux le faire remonter dans la sous-requète afin d'avoir moins de résultat retourné à traiter par la suite.
 
Enfin, de toute façon, telle qu'elle est là, ta requète fait trop de boulot. tu fais une jointure à chaque fois avec protie alors qu'il n'est jamais utilisé.
 

Reply

Marsh Posté le 26-07-2004 à 14:48:49    

mets l'explain plan de ta requête actuelle dans le 1er post ;)

Reply

Marsh Posté le 26-07-2004 à 15:25:59    

Gizmo >  
 
Ben si, protie est utilisé :
" || allpro.codprotie" à la fin du select le plus imbriqué.
 
Sinon, je ne comprends pas le début de ton post. De toute façon, lors de l'éxécution, Oracle n'éxécute pas les requêtes telles qu'elles, tous les filtres sont descendus au plus pas niveau possible, donc le codsoc s'applique jusqu'au plus bas niveau de sous-requête. De ce côté, il n'y a aucun problème, ça ne changera rigoureusement rien.
 
C'est juste la concaténation et le like qui me pose problème, je pense que si je testais champ par champ, ça pourrait être plus rapide, mais je n'en suis pas sûr du tout... C'est surtout là qu'une optimisation serait utile.

Reply

Marsh Posté le 26-07-2004 à 15:27:37    

Beegee > Hmmm, je vais voir si je peux poster l'explain plan. Rien n'est moins sûr, car je n'ai ni les outils nécessaires ni les droits :/

Reply

Marsh Posté le 26-07-2004 à 15:42:11    

Au fait, truc que je n'ai pas précisé. CODSOC est un champ systématiquement présent dans toutes les requêtes de la base, il fait partie de la clé unique de chaque table.
Il s'agit du numéro de société rattaché, ce qui permet une gestion multi-société de l'ERP, et à terme du site web.

Reply

Marsh Posté le 26-07-2004 à 15:46:55    

une petite remarque si tu concerves la concaténation de tous les champs : tu risques de trouver des lignes du type :
allpro.codpro = 'totopap'
allpro.motcle = 'ierstata'
 
alors que je ne pense pas que tu les veuilles :D
 
Donc pense à mettre des caractère spéciaux entre chaque couplet de champs concaténés ... ou alors reviens à un like sur chaque champ.
 
L'avantage du like sur chaque champ, c'est quand même de filtrer dès le début les informations, ce qui permet de n'arriver très rapidement qu'à un très petit nombre de lignes manipulées :)

Reply

Marsh Posté le 26-07-2004 à 18:08:56    

J'y avais pensé et j'ai modifié en effet, j'ai ajouté des espaces entre chaque champs que je concatène ;)
 
Et il y aura autant de like que de mots saisis, donc plus de problème :)


Message édité par Arjuna le 26-07-2004 à 18:09:10
Reply

Sujets relatifs:

Leave a Replay

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