Question

Tout à coup (mais malheureusement, je ne sais pas quand « soudainement » était, je le sais bien couru à un moment donné dans le passé) un de mes requêtes a commencé à prendre 7+ secondes au lieu de millisecondes à exécuter. J'ai 1 table locale et 3 tables étant accessibles via un lien DB. Les 3 tables distantes sont reliées entre elles, et l'un d'entre eux est jointe à ma table locale.

La clause de la table locale où prend quelques seulement Millis d'exécuter lui-même, et ne retourne que quelques-uns (10 ou 100 de plus) les dossiers. Les 3 tables distantes ont plusieurs centaines de milliers, peut-être des millions de dossiers entre eux, et si je les rejoins convenablement je reçois des dizaines ou des centaines de milliers d'enregistrements.

Je ne rejoins les tables distantes afin que je puisse retirer quelques morceaux de données relatives à chaque enregistrement de ma table locale.

Ce qui semble se produire, cependant, est que Oracle rejoint les tables à distance ainsi que d'abord, puis ma table locale à ce désordre à la fin. Cela va toujours être une mauvaise idée, surtout compte tenu de l'ensemble de données qui existe en ce moment, alors j'ai ajouté un soupçon de /*+ LEADING(local_tab remote_tab_1) */ à ma requête et retourne maintenant en millisecondes.

Je comparais expliquer les plans et ils sont presque identiques, sauf pour une seule BUFFER SORT sur l'une des tables distantes.

Je me demande ce qui pourrait causer Oracle d'aborder ce dans le mauvais sens? Est-ce un problème d'index? Que dois-je chercher?

Était-ce utile?

La solution

Lors du choix d'un plan d'exécution, Oracle estime que les coûts pour les différents plans. Une information cruciale pour cette estimation est la quantité de lignes va se passer une étape du plan d'exécution. Oracle tente d'estimer ceux qui utilisent « statistiques », à savoir des informations sur le nombre de lignes d'une table contient, combien de valeurs différentes une colonne contient; Comment ces valeurs sont uniformément réparties.

Ces statistiques sont juste que les statistiques, et ils pourraient se tromper, ce qui est l'une des raisons les plus importantes pour les erreurs de jugement de l'optimiseur oracle.

Ainsi la collecte de nouvelles statistiques comme décrit dans un commentaire pourrait aider. Jetez un oeil à la documentation sur ce paquet DBMS_STATS. Il existe de nombreuses façons d'appeler ce paquet.

Autres conseils

Un problème commun que je suis venu à travers est une requête qui joint plusieurs tables, où les jointures forment une chaîne d'un bout à l'autre, par exemple:.

SELECT *
FROM   tableA, tableB, tableC, tableD, tableE
WHERE  tableA.ID0 = :bind1
AND    tableA.ID1 = tableB.ID1
AND    tableB.ID2 = tableC.ID2
AND    tableC.ID3 = tableD.ID3
AND    tableD.ID4 = tableE.ID4
AND    tableE.ID5 = :bind2;

Remarquez comment l'optimisateur peut choisir de conduire la requête à partir tableA (par exemple si l'indice sur ID0 est bien sélectif) ou de tablée (si l'indice sur tableE.ID5 est plus sélectif).

Les statistiques sur les tables pourraient faire le choix entre ces deux plans d'équilibre sur un couteau; un jour, il fonctionne très bien (conduite de tableA), le lendemain de nouvelles statistiques sont recueillies et tout d'un coup, le plan alternatif de conduite tablée a un coût moindre et est choisi.

Dans ce cas, l'ajout d'un soupçon interlignage est une façon pour pousser en arrière au plan initial (c.-à-voiture de tableA) sans imposer trop à l'Optimiseur (il ne force pas la Optimiseur de choisir toute particulière méthodes de jointure).

Vous faire distribuer l'optimisation des requêtes, et c'est une bête délicate. Il se pourrait que les tables du système distant sont hors de déséquilibrés ou sont en cours de votre tableau de statistiques, mais maintenant ont changé. Ou le système distant ajouté / supprimé / index modifiés, et qui a cassé votre plan. (Ceci est une excellente raison de considérer la réplication -. Vous pouvez donc contrôler les index et statistiques contre elle)

Cela dit, l'estimation Oracle de cardinalité est le principal moteur dans le plan d'exécution. Une analyse de trace 10053 (Jonathan Lewis livre Principes de base Oracle basés sur les coûts a des exemples merveilleux de 8i à 10.1) peut contribuer à éclairer pourquoi votre déclaration est maintenant cassé et comment l'indice de LEADING le fixe.

L'indice de DRIVING_SITE pourrait être un meilleur choix si vous savez que vous voulez toujours les tables locales à assembler avant d'aller après le site distant; il clarifie votre intention sans entraîner le plan de la façon dont un indice LEADING serait.

Peut-être pas pertinent, mais j'ai eu une situation similaire une fois où la table à distance avait été remplacée par une vue unique table. Quand il était une table l'optimiseur de requêtes distribuées « vu » qu'il avait un indice. Quand il est devenu une vue, il ne pouvait pas voir l'index plus et ne pouvait pas coûter un plan qui a utilisé un index sur l'objet distant.

C'était il y a quelques années. Je documenté mon analyse au moment ici .

RI,

Il est difficile d'être sûr de la cause des problèmes de performance sans voir le SQL.

Lorsqu'une requête Oracle exécutait bien avant, et se met soudain fonctionne mal, est généralement liée à l'une des deux questions:

  

A) Les statistiques sont périmées. Ceci est le plus facile et plus rapide chose à vérifier, même si vous avez un processus de traitement par lots de ménage qui est censé prendre soin ... toujours revérifier.

     

B) Volume de données / données changement de modèle.

Dans votre cas, l'exécution d'une requête distribuée sur plusieurs bases de données rend 10x plus difficile pour Oracle pour gérer la performance entre eux. Est-il possible de mettre ces tables dans une base de données, les propriétaires de schéma peut-être séparés dans une base de données?

Les conseils sont notoirement fragiles, comme Oracle est sous aucune obligation de suivre l'indice. Lorsque le volume de données ou le modèle change un peu plus, Oracle peut simplement ignorer le message et faire ce qu'il pense être le mieux (ie pire, -.).

Si vous ne pouvez pas mettre ces tables en une seule base de données, alors je vous recommande de regarder casser votre requête en deux déclarations:

  1. INSERT sur la sous-SELECT pour copier des données externes à une table temporaire globale dans votre base de données actuelle.
  2. SELECT de la table temporaire globale à se joindre à votre autre table.

Vous aurez un contrôle total sur la performance de l'étape 1 ci-dessus sans avoir recours à des conseils. Cette approche échelles généralement bien, vous offrir de prendre le temps de faire le réglage des performances. Je l'ai vu cette approche résoudre de nombreux problèmes de performances complexes.

Les frais généraux pour Oracle pour créer une nouvelle table entière, ou insérer un tas de dossiers, est beaucoup plus petite que la plupart des gens attendent. La définition d'une table temporaire globale plus réduit que les frais généraux.

Matthieu

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top