2010-10-20 5 views
7

Je trouve ce paragraphe dans la documentation OracleOrdre des tables dans requête de jointure

si vous voulez sélectionner le nom de chaque département ainsi que le nom de son gestionnaire , vous pouvez écrire la requête dans un de deux façons. Dans le premier exemple qui suit, l'indice ++ ordonné ++/ indique que pour faire la jointure dans l'ordre, les tables apparaissent dans la clause FROM avec en essayant d'optimiser l'ordre de jointure.

SELECT /*+ordered*/ d.NAME, e.NAME 
FROM DEPT d, EMP e WHERE d.MGR = e.SS# 

ou:

SELECT /*+ordered*/ d.NAME, e.NAME 
FROM EMP e, DEPT d WHERE d.MGR = e.SS# 

Supposons qu'il ya 10 départements et 1000 employés, et que la table intérieure dans chaque requête a un index sur la colonne de jointure. Dans la première requête, la première table produit 10 lignes qualifiantes (dans ce cas, la table entière). Dans la deuxième requête, la première table génère 1000 lignes qualifiantes. La première requête accédera à la table EMP 10 fois et analysera la table DEPT une fois. La deuxième requête analyse une fois la table EMP , mais accède 1000 fois à la table DEPT . Par conséquent, la première requête fonctionnera beaucoup mieux. En règle , les tables doivent être disposées à partir des plus petites lignes de nombre effectif au plus grand nombre effectif de lignes . La taille de ligne effective d'une table dans une requête est obtenue par en appliquant les conditions logiques que sont résolues entièrement sur cette table.

Mais je ne comprends pas correctement cela. S'il y a m lignes dans la table t1 et n lignes dans la table t2, le moteur sql ne passerait-il pas par m x n lignes dans les deux cas?

Mise à jour: Merci pour toutes les réponses. Je ne vais pas remplacer l'optimiseur, je voulais juste confirmer ma pensée.

+2

Pouvez-vous s'il vous plaît poster un lien vers le document où vous lisez ceci? –

+0

Il vous manque la clause 'WHERE' dans votre deuxième requête, qui se trouve dans la documentation Oracle. –

+0

@Peter - Ajouté où clause :) – Jerry

Répondre

2

Cela dépend de l'instruction WHERE.

SELECT /++ordered++/ d.NAME, e.NAME FROM DEPT d, EMP e WHERE d.MGR = e.SS# 

Sélectionne tous les responsables de chaque département. Comme il y a 10 départements, cela entraîne la récupération de 10 enregistrements.

SELECT /++ordered++/ d.NAME, e.NAME FROM EMP e, DEPT d 

Cela permet de sélectionner tous les employés avec le nom du département qu'ils travaillent. Comme il y a 1000 employés, votre resultset aura 1000 lignes.

JOIN ne causera jamais votre moteur à boucle sur m x n lignes, vous êtes d'une resultset jointure interne sera toujours m si m < n

+0

Je ne comprends pas ce que vous voulez dire par "resultset d'une jointure interne sera toujours m x m si m

+0

Est-ce vrai même s'il n'y a pas d'index sur les clés de jointure? (Encore une fois, c'est juste pour la connaissance.Je comprends que les jointures sur les non-index n'est pas recommandé.) – Jerry

+0

@Tony, Cela dépend de votre clause WHERE/ON. Dans le premier cas, le jeu de résultats contiendra 10 lignes, dans la seconde 1000. @Jerry Que voulez-vous dire par index sur les clés de jonction? – thomaux

4

Eh bien, dans le premier cas, le nombre de lectures logiques est de 10 + 10 , dans la seconde 1000 + 1000, chaque département étant lu en moyenne 100 fois.Cependant, l'écriture de requêtes avec l'instruction ORDERED comme ceci n'est pas une pratique normale. Il est préférable de laisser l'optimisation à l'optimiseur la plupart du temps.

Je ne suis pas sûr exactement de quelle documentation vous avez reçu cette citation, mais où je l'ai vu il est précédé par ce paragraphe très important que vous avez omis. Je cite ici au profit d'autres personnes qui pourraient autrement penser cette méthode de requêtes d'écriture standard:

optimiseur Normalement prend le meilleur plan d'exécution, un ordre optimal des tables à assembler. Dans le cas où l'optimiseur ne produit pas un bon plan d'exécution , vous pouvez contrôler l'ordre d'exécution à l'aide de la fonction HINTS SQL. Pour plus d'informations, voir Oracle Database Lite SQL Référence.

- Oracle® Database Lite Developer's Guide

+2

+1, même si je pense qu'il suppose une NESTED LOOP JOIN (un HASH JOIN serait probablement choisi s'il n'y a pas de condition de filtre). Le fait que le doc suppose une jointure de boucle imbriquée (RULE optimizer?) Et préconise l'utilisation d'astuces me fait penser que ce conseil provient d'un doc très ancien (Oracle 7?). Quoi qu'il en soit, un bon conseil pour laisser l'optimiseur faire son travail. –

1

Vous avez vraiment trouvé que dans docs oracle?

Vous ne devriez pas utiliser l'indice ORDERED et laisser Oracle prendre la décision pour vous - cela fonctionne la plupart du temps très bien de nos jours. Cependant, l'ordre de jointure fait une différence en termes de performances.

L'exemple semble discuter des IMBRIQUÉS rejoindre BOUCLES:

Case 1: 
-> 1 lookup to find 10 rows in table A 
-> 10 index lookups in table B 

Case 2: 
-> 1 lookup to find 1000 rows in table B 
-> 1000 index lookups in table A