2010-08-11 4 views
5

Voici ma question:Pourquoi cette requête aboutit-elle à un MERGE JOIN CARTESIAN dans Oracle?

select count(*) 
from email_prod_junc j 
inner join trckd_prod t5 on j.trckd_prod_sk = t5.trckd_prod_sk 
inner join prod_brnd b on t5.prod_brnd_sk = b.prod_brnd_sk 
inner join email e on j.email_sk = e.email_sk 
inner join dm_geography_sales_pos_uniq u on (u.emp_sk = e.emp_sk and u.prod_brnd_sk = b.prod_brnd_sk) 

L'expliquer le plan dit:

cartésienne jointure entre DM_GEOGRAPHY_SALES_POS_UNIQ et EMAIL_PROD_JUNC.

Je ne comprends pas pourquoi parce qu'il y a une condition de jointure pour chaque table.

+4

Est-ce que la fusion de cartes cartésiennes entraîne des problèmes de performances ou ne vous attendez-vous pas à la voir? Si l'une des tables que vous rejoignez pour avoir un petit nombre de lignes fusionne, la fonction cartésienne peut être invoquée. La version Oracle serait également utile car les optimiseurs sont beaucoup modifiés/améliorés d'une version à l'autre. –

+0

Oui, la requête a pris plus d'une minute pour revenir avec la jointure cartésienne. Une fois que j'ai ajouté l'indice ordonné, il est revenu en <1s. C'est Oracle 10g. Trckd_Prod et Prod_Brnd sont des petites tables, les 3 autres sont très grandes. –

+0

@MarkSherretta - l'optimiseur 10g est connu pour être floconneux et pour exiger des conseils dont les versions ultérieures de l'optimiseur n'ont pas besoin. 11,1 est assez solide - 11,2 mieux. Je n'ai aucune expérience personnelle avec 12 donc je ne peux pas dire comment ça se passe. –

Répondre

5

Je résolu ce problème en ajoutant l'indice ORDONNÉ:

select /*+ ordered */ 

Je suis les informations de here

Si vous spécifiez les tables dans l'ordre que vous voulez les rejoignirent et utilisez cette astuce, Oracle ne sera pas passer du temps à essayer de comprendre la jointure optimal commande, il suffit de rejoindre eux comme ils sont commandés dans la clause FROM.

+0

Est-ce que ce changement a affecté la performance? – Allan

+0

Oui, les performances sont passées de> 1 minute à <1s. –

0

Je voudrais spéculer que cela se produit en raison de la condition sur (x et y) de la dernière jointure interne. Oracle ne sait probablement pas comment optimiser la condition multi-instructions, donc il fait une jointure complète, puis filtre le résultat par la condition après le fait. Je ne suis pas vraiment familier avec le plan d'expliquer Oracle, donc je ne peux pas dire que l'autorité

Modifier

Si vous voulez tester cette hypothèse, vous pouvez essayer de changer la requête:

inner join dm_geography_sales_pos_uniq u on u.emp_sk = e.emp_sk 
where u.prod_brnd_sk = b.prod_brnd_sk 

et voir si cela élimine la jointure complète du plan

+1

Merci RMorrisey, mais cela n'a pas fonctionné, il en résulte le même plan d'exécution. –

1

Sans connaître vos index et le plan complet, il est difficile de dire pourquoi cela se passe exactement. Ma meilleure estimation est que EMAIL_PROD_JUNC et DM_GEOGRAPHY_SALES_POS_UNIQ sont relativement petits et qu'il y a un index sur TRCKD_PROD (trckd_prod_sk, prod_brnd_sk). Si tel est le cas, l'optimiseur peut avoir décidé que le cartésien sur les deux tables plus petites est moins cher que de filtrer deux fois TRCKD_PROD.