Optimisation de requête [SGBD/SQL] - SQL/NoSQL - Programmation
Marsh Posté le 25-06-2004 à 15:05:32
Arjuna a écrit : Un SGBD-R permet de gérer les relations entre les éléments, et de les "enforce", c'est à dire d'en assurer l'intégrité. |
Marsh Posté le 25-06-2004 à 15:18:55
MagicBuzz a écrit il y longtps : Grossomodo : |
Marsh Posté le 25-06-2004 à 15:49:29
Citation : |
je croyait qu'il y avait des optimisations avec les stats de la base et que les requêtes ci-dessus revenaient au même... Me trompais-je ?
edit : ortho
Marsh Posté le 25-06-2004 à 16:32:39
Les stats sont bien, mais sur une base très solicitée, il y a un temps plus ou moins important avant qu'elles soient recomputées.
Dans la base d'un ERP par exemple, qui va se taper quelques milliers de connections concurrentes pendant 10 heures d'affilée par jour, les stats sont carrément mise à jour a la main par batch au heures creuses (ça consomme énormément le régénération des stats).
De ce fait, si les stats permettent en effet en temps normal de corriger les lacunes de la première requête, ils faut systématiquement écrire ses requêtes comme si elles n'existaient pas.
Marsh Posté le 26-06-2004 à 09:32:10
les stats sur les tables ne sont pas nécessairement regardées ... Sous Oracle par exemple, il y a 2 modes de fonctionnements d'une base : choose (optimisation en regardant les stats) / rule (optimiseur de requête se basant sur les index, etc.).
Dans les 2 cas, il me semble que l'ordre des éléments dans les clauses where importe peu, l'optimiseur va de lui-même prendre le chemin le plus rapide ... mais il fait de son mieux, et de temps en temps, il faut l'aider
D'où les 'hints' en Oracle, ces petites indications qu'on fournit pour forcer l'interprétation d'une requête dans un sens précis.
Exemple :
select /*+ index(code code_index) */ *
from code
where id_code = 1;
Avec le hint '/*+ index(code code_index) */' on force Oracle à prendre l'index code_index de la table code. (il l'aurait pris par défaut de toute façon, soit s'il est en mode rule car l'index est là, soit en mode choose si les stats sont à jour).
Il y a énormément de hints Oracle, pas tous documentés d'ailleurs, qui permettent d'avoir l'explain plan qu'on veut ...
On peut par exemple forcer l'interprétation de la where clause dans l'ordre dans lequel elle est écrite, ou encore dire si on veut faire des 'nested loops' ou 'hash join', etc.
Marsh Posté le 27-06-2004 à 01:39:43
Beegee > Tu as l'air de bien maîtriser le sujet des hints pour oracle.
A propos du forçage des index, j'ai découvert le hint que tu cites il y a quelques jours (j'ai une requête qui dure des heures, et je n'arrive pas à en réduire le temps).
J'ai donc trouvé la syntaxe /* +index([table] [index]) */
Seulement, dans mon cas, c'est légèrement plus compliqué...
En effet, j'utilise 5 fois la même table (aliasée) dans la même requête, en utilisant des index différents.
Est-ce que dans le hint, on peut remplacer le nom de la table par son alias ? Si non, comment puis-je faire ?
Marsh Posté le 27-06-2004 à 09:18:49
oui, tu peux utiliser les alias
mais y a peut-être aussi moyen d'améliorer ta requête, parce que utiliser 5 fois la même table dans une requête c'est un peu trop ...
Marsh Posté le 27-06-2004 à 20:21:39
Ben j'ai pas d'autre choix...
La table contient un calendrier des jours fériés. Et dans ma requête je fais 5 différences de dates sur 5 périodes différentes...
Marsh Posté le 27-06-2004 à 20:23:25
Ben si tu peux, poste la requête ...
tu es vraiment obligé de tout renvoyer en une requête ? tu peux pas faire plusieurs petites requêtes ? Vu comme tu le présentes, je comprends pas trop l'intérêt de grouper le résultat en un requête ...
Marsh Posté le 27-06-2004 à 20:34:57
Parceque la requête renvoie des informations sur la performance des fournisseurs de l'entreprise ou je suis.
Et les 67 000 lignes générées (infos sur les 6 derniers mois) sont ensuite traîtées dans Excel afin de faire une chiée de calculs et générer divers rapports et graphs.
Sur le poste des personnes qui utiliseront la macro, il n'y a pas Oracle Client, et il est impossible qu'ils le mettent (contraintes logicielles au niveau du groupe)
Ainsi, mla macro passe par une requête HTTP sur une page intranet, qui renvoie les données au format CSV. Ce système étant extrêment lent, je doit donc récupérer un maximum d'infos (pour le moment toutes) puis faire mes traîtements de regroupement et filtres à la main dans ma macro, plutôt que par exemple générer 67000 * 5 requêtes HTTP afin de retrouver les infos de chaque ligne utilisée...
Ca va faire deux semaines que je retourne le problème dans tous les sens, et je commence à sècher complètement
Là on est en train d'essayer de stocker les données de la requête dans une table temporaire, mise à jour toutes les semaines... Seulement la requête actuelle semble durer plus de 12 heures, et il faut donc qu'on trouve une solution pour arriver à faire marcher cette solution de rattrappage. En fait, on ne comprend même pas pourquoi c'est aussi lent. Tous les index nécessaires sont créés et opérationnel, et le serveur encaisse des requêtes bien plus complexes et volumineuse sans problème... J'ai mis un DBA sur le coup pour voir s'il trouve une explication en monitorant de plus près le SGBD (rien à tirer du plan d'éxécution, il est clean, il ne reste plus aucun range scan ni rien...). Mais vu que c'est le closing actuellement (Q2) toutes les équipes systèmes sont full-time pour la maintenance et garantir qu'aucun problème ne puisse arriver en cette période critique de l'année... J'espère que d'ici 1 ou 2 semaines j'aurai une réponse de sa part, et qui m'éclairera
Marsh Posté le 27-06-2004 à 20:37:19
Elle a pas mal changé depuis, mais elle reste globalement la même (avec les bugs en moins, j'ai corrigé quelques inepties depuis).
http://forum.hardware.fr/hardwaref [...] 3420-1.htm
Demain je te poste la version actuelle si tu veux.
Marsh Posté le 27-06-2004 à 20:41:11
D'ailleurs, en relisant le post initial, j'aurais mieu fait de ne pas corriger les bugs
Je suis passe de 17 000 à 67 000 lignes (aucun doublon) et de 30 minutes à une journée
J'ai réussi à la faire tourner un coup, en la lançant le matin en arrivant, j'ai retrouvé les résultat le lendemain matin, a priori elle a fini avant minuit, heure à laquelle Oracle est descendu afin de faire un backup a froid.
Marsh Posté le 27-06-2004 à 20:42:13
12h pour renvoyer en tout seulement 67000 lignes ? elle doit être méchante la requête
Moi je suis sur une migration de données assez conséquente (un des batches doit extraire plus de 90.000.000 lignes d'une table, en faisant quelques jointures sur d'autre ), mais on a réussi à faire tomber la durée d'exécution à environ 2h30, ce qui est plutôt correct vu le volume de données (on est limités par les performances moyennes de la baie de disques ).
Pour ton problème, si tu donnes pas plus d'infos, je vais pas pouvoir t'aider :|
edit : ah oui, je me souviens de ton sujet
Marsh Posté le 27-06-2004 à 20:43:49
Le problème c'est que dimanche je ne suis pas à mon boulot
Je te poste le tout demain (requête + vue) histoire de voir à quoi ça ressemble. Tu me demanderas s'il y a des trucs que tu ne comprends pas dans la vue, parceque le modèle des données est relativement compliqué )
Marsh Posté le 27-06-2004 à 20:49:40
ce qui est assez étrange, c'est qu'avec une requête aussi symétrique, on arrive pas à simplifier ...
enfin je veux dire : y a apparemment pas de vraie jointure entre tes cap<X> ... tu as essayé déjà de faire une vue sur ta table cap qui filtre sur :
cap1.codsoc(+) = 0
and cap1.codcal(+) = 'FER'
et de l'utiliser au lieu de la table cap directement ?
A mon avis faut chercher dans ce sens ...
et ne pas hésiter à faire des sous-requêtes si possible, pour réduire le volume de données manipulées dès le début.
Marsh Posté le 27-06-2004 à 22:31:58
codsoc / codcal / datfin étant l'index unique de la table (la clé) je ne pense pas qu'une vue doit vraiment utile.
Deplus, toutes les lignes ont codsoc à 0 (l'ERP a un support multi-SOCiété, mais ici seule une instance est installée), et FER est correspond à 80% des lignes. A partir de là, utiliser une vue pour réduire le nombre de lignes lues ne me semble pas super intéressante.
Je garde quand même l'idée sous le coude, demain je doit finir la rédaction de la documentation fonctionnelle d'un projet que je dois démarrer dans la semaine, mais si j'ai le temps, je ne manquerai pas de faire le test, de toute façon je ne risque rien à essayer
Sinon, la jointure se fait uniquement sur les champs date.
Toutes les périodes fériées qui se terminent durant la période étudiée sont réputées comme complètes (tant pis si quelques lignes peuvent être saisies pendant un week-end, l'erreur indûe ne justifie pas une complexification de la requête), donc je n'ai qu'à prendre les périodes fériées qui se terminent dans la période étudiée pour connaître le nombre de jours fériés dans ma période.
Pas besoin de faire intervenir la date de début, car non seulement j'aurai peut-être quelques lignes de moins (beaucoup moins de 1%), mais surtout ce champ n'étant pas indexé, je perdrais en performances.
Je te poste le détail de tout ce bronx demain.
Chose amusant à noter d'ailleurs, c'est qu'au départ j'avais oublié de faire une jointure externe, et depuis que je l'ai mise, la requête est plus rapide (sauf qu'elle s'est complexifiée depuis donc elle est plus lente mais bon )
Marsh Posté le 01-07-2004 à 09:12:35
Quelques notes intéressantes sur :
- Le probleme une table/utilisateur (cai mal)
- Ne pas mettre de clé primaire dans une table (cai mal)
- Les tables isolés dans le modèle
Arjuna et Jagstang ont écrit : |
Le débat sur le fait de mettre des clés primaires (ou non) va surement continuer ici http://forum.hardware.fr/hardwaref [...] 4188-1.htm
Marsh Posté le 25-06-2004 à 15:04:01
Bonjour,
j'ai fait ce topic dans le but de recueillir le maximum d'informations concernant les différentes optimisations que vous avez faites sur des requêtes.
Il est donc là dans le but de discuter des différentes solutions que vous trouvez à un problème.
J'essaierai de regrouper les différentes remarques qui seront postées sur le forum.
Merci de préciser le SGBD dont vous parlez au début de votre post pour éviter toute confusion.
Les liens sont également la bienvenue.
Merci