Joindre la jointure externe sur un problème de performances sur deux colonnes
Je suis en utilisant une requête SQL qui est similaire à la forme suivante:
SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.person_uid = table2.person_uid
AND table1.period = table2.period
Et c'est soit trop lent ou quelque chose du blocage, car il faut au moins 4 minutes pour revenir. Si je devais le changer à cela:
SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.person_uid = table2.person_uid
WHERE table1.period = table2.period
puis il fonctionne très bien (mais ne retourne pas le bon nombre de colonnes). Est-il un moyen pour accélérer le processus?
Mise à JOUR: Il fait la même chose si je passe les deux dernières lignes de la dernière requête:
SELECT col1, col2
FROM table1
LEFT OUTER JOIN table2
ON table1.period = table2.period
WHERE table1.person_uid = table2.person_uid
Mise à JOUR 2: ce sont en fait des points de vue que je vais rejoindre. Malheureusement, ils sont sur une base de données je n'ai pas le contrôle, donc je ne peux pas (facilement) apporter des modifications à l'indexation. Je suis enclin à penser que c'est un problème d'indexation. Je vais attendre un peu avant d'accepter une réponse dans le cas où il y a un peu de magie pour accorder cette requête que je ne connais pas. Sinon, je vais accepter l'une des réponses et essayer de trouver un autre moyen de faire ce que je veux faire. Merci pour tout le monde de l'aide pour l'instant.
source d'informationauteur Jason Baker
Vous devez vous connecter pour publier un commentaire.
Garder à l'esprit que les états 2 et 3 sont différentes de la première.
Comment? Eh bien, vous êtes en train de faire une jointure externe gauche et votre clause where n'est pas prise en compte (comme la clause n'). Au minimum, essayez de:
et voir si vous obtenez le même problème de performance.
Quels indices avez-vous sur ces tables? Ce lien est défini par une contrainte de clé étrangère?
Ce que vous avez probablement besoin est un indice composite sur les deux person_uid et de la période (sur les deux tableaux).
Je pense que vous avez besoin de comprendre pourquoi les deux derniers ne sont pas de la même requête que la première. Si tu fais une jointure gauche, puis ajouter une clause where referncing un champ de la table sur le côté droit de la jointure (celui qui ne peut pas toujours avoir un dossier pour le match de la première table), alors vous avez effectivement changé le rejoindre pour une jointure interne. Il y a une exception à cela et c'est si vous faites référence à quelque chose comme
Dans ce cas, vous pour demander la notice qui n'ont pas d'enregistrement dans la seconde table. Mais à part ce cas particulier, vous sont en train de changer la gauche se joindre à une jointure interne si vous référence à un champ dans table2 dans la clause where.
Si votre requête n'est pas assez rapide, je regarde votre indexation.
Toute ce que l'on vous raconte sur la base des informations que vous avez fourni est une supposition.
Regarder le plan d'exécution de la requête. Si vous ne voyez pas de raison de la lenteur dans le plan, le poste le plan ici.
http://download.oracle.com/docs/cd/B28359_01/server.111/b28274/ex_plan.htm#PFGRF009
Avez-vous de la couverture des index sur
person_uid
etperiod
pour les deux tableaux?Si pas, ajoutez-les et essayez à nouveau.
Prendre un coup d'oeil à l'exécution du plan et de voir ce que la requête est en train de faire.
Aussi: Quels sont les types de données des champs? Sont-ils les mêmes dans les deux tables? Un cast implicite peut vraiment ralentir les choses.
Faire de ces tables, les index sur les colonnes de vous joindre? Installer Oracle gratuit SQLDeveloper produit et de l'utiliser pour faire un "expliquer" sur cette requête et voir si c'est de faire des analyses séquentielles de deux tables.
Dans une jointure gauche, vous seriez de numérisation table1 pour chaque combinaison unique de (person_uid,période), puis la recherche de table2 pour tous les enregistrements correspondants. Si table2 n'ont pas un indice approprié, il peut s'agir de la numérisation de l'ensemble de la table aussi.
Ma meilleure supposition, sans voir un plan d'exécution, c'est que la première requête (le seul qui semble être correct) est d'avoir à l'analyse de la table table2 ainsi que table1.
Que vous dites que vous ne pouvez pas modifier l'index, vous devez modifier la requête. Aussi loin que je peux dire, il y a une seule alternative réaliste...
L'espoir ici est que vous pouvez numériser la table2 pour chaque combinaison unique de (person_uid, période), mais utiliser des indices sur la table1. (Par opposition à la numérisation de table1 et utilisation des indices sur table2, ce que j'attendais de votre requête.)
Si table1 n'a pas l'index approprié, cependant, vous aurez très peu de chance de voir tout l'amélioration de la performance à tous les...
Dems.
Dans l'une des mises à jour de l'OP, il dit qu'il est en fait de l'interrogation des vues pas les tables. Dans ce cas, le rendement pourrait bien être augmentée en interrogeant directement les tables dont il a besoin, surtout si les points de vue sont complexes et se joindre à de nombreuses autres tables qui ne contiennent pas les informations dont il a besoin ou qu'ils sont des vues de cet appel vues.
Syntaxe de jointure ANSI fournit une distinction très nette entre les conditions de JOINTURE et les prédicats de FILTRE; ce qui est très important lors de l'écriture des jointures externes. À l'aide de l'emp/dept tables, regardez les résultats de ces deux jointures externes
T1
====
Le premier exemple, T1 montre est un exemple de "se joindre à une constante". Essentiellement, la condition de filtre est appliqué avant d'effectuer la jointure externe. Si vous éliminez les lignes, qui sont ensuite rajoutés dans le cadre de la jointure externe. Ce n'est pas forcément faux, mais c'est que la requête que vous avez vraiment demandé? Souvent, c'est les résultats présentés dans le T2 qui sont nécessaires, dans laquelle le filtre est appliqué après le (externe) rejoignez.
Il y a également une performance implication trop, pour de grands ensembles de données. Dans de nombreux cas, le rejoindre sur un constante doit être résolu en interne par l'optimiseur par la création d'une vue latérale, qui peut généralement être optimisé via une jointure de boucle imbriquée plutôt que d'une jointure de hachage
Pour les développeurs qui sont familiers avec l'Oracle syntaxe de jointure externe, la requête aurait probablement été écrit comme
Cette requête est sémantiquement équivalent à Q2 ci-dessus.
Donc en résumé, il est extrêmement important que vous compreniez la différence entre la clause de JOINTURE et la clause where lors de l'écriture de la norme ANSI jointures externes.