2009-05-12 4 views
3

Lors de la jonction entre tables (comme dans les exemples ci-dessous), existe-t-il une différence d'efficacité entre joindre sur les tables ou joindre des sous-requêtes contenant uniquement les colonnes nécessaires? En d'autres termes, y a-t-il une différence d'efficacité entre ces deux tables?Table Join Efficiency Question

SELECT result 
    FROM result_tbl 
    JOIN test_tbl     USING (test_id) 
    JOIN sample_tbl     USING (sample_id) 
    JOIN (SELECT request_id 
      FROM request_tbl 
     WHERE request_status='A') USING(request_id) 

vs

SELECT result 
    FROM (SELECT result, test_id FROM result_tbl) 
    JOIN (SELECT test_id, sample_id FROM test_tbl) USING(test_id) 
    JOIN (SELECT sample_id   FROM sample_tbl) USING(sample_id) 
    JOIN (SELECT request_id 
      FROM request_tbl 
     WHERE request_status='A')     USING(request_id) 
+0

Bonne question - Je vais laisser quelqu'un de mieux répondre, mais mon intuition est que les deux sont à peu près les mêmes en termes d'efficacité, puisque le moteur DB doit rejoindre sur le même nombre de colonnes dans les deux cas au même nombre de lignes (même si moins de champs sont impliqués). Corrige moi si je me trompe! – AndreiM

+0

Mark Brady aurait aimé cette question, mais nooooo .... Les élitistes autour d'ici l'ont effrayé avec leur pouvoir. – TheSoftwareJedi

+0

Fermer cette question n'est plus pertinent car tout le monde sait que SQL Server est meilleur et nous n'aurions même pas à demander cela. – TheSoftwareJedi

Répondre

4

Il n'a pas d'importance. Il peut effectivement être pire puisque vous prenez le contrôle de l'optimiseur qui sait généralement le mieux. Cependant, souvenez-vous que si vous faites un JOIN et que vous incluez seulement une colonne de l'une des tables, il est préférable de la réécrire comme une série d'instructions EXISTS - parce que c'est ce que vous voulez vraiment dire. JOINs (avec quelques exceptions) rejoindra les lignes correspondantes, ce qui représente beaucoup plus de travail pour l'optimiseur.

par exemple.

SELECT t1.id1 
    FROM table1 t1 
INNER JOIN table2 ON something = something 

doit presque toujours être

SELECT id1 
    FROM table1 t1 
WHERE EXISTS(SELECT * 
       FROM table2 
       WHERE something = something) 

Pour les requêtes simples l'optimiseur peut réduire la requête plans en les identiques. Vérifiez-le sur votre SGBD.

Aussi ceci est une odeur de code et devrait probablement être changé:

JOIN (SELECT request_id DE request_tbl OU request_status = 'A')

à

SELECT result 
    FROM request 
WHERE EXISTS(...) 
    AND request_status = 'A' 
5

La seule façon pour en savoir à coup sûr est de courir à la fois avec le suivi activé et ensuite regarder le fichier de trace. Mais selon toute probabilité, ils seront traités de la même manière: l'optimiseur fusionnera toutes les vues en ligne dans l'instruction principale et élaborera le même plan de requête.

2

Aucune différence. Vous pouvez dire en exécutant EXPLAIN PLAN sur ces deux instructions - Oracle sait que tout ce que vous voulez est la colonne "résultat", donc il ne fait que le minimum nécessaire pour obtenir les données dont il a besoin - vous devriez trouver que les plans seront être identique. L'optimiseur Oracle matérialise parfois une sous-requête (c'est-à-dire exécute la sous-requête et conserve les résultats en mémoire pour une réutilisation ultérieure), mais cela est rare et ne se produit que lorsque l'optimiseur pense que cela améliorera les performances. ; Dans tous les cas, Oracle effectuera cette "matérialisation", que vous ayez spécifié les colonnes dans les sous-requêtes ou non.

De toute évidence, si le seul endroit où la colonne "results" est stockée est dans les blocs (avec le reste des données), Oracle doit visiter ces blocs - mais il ne conservera que les informations pertinentes (le "résultat" colonne et autres colonnes pertinentes, par exemple "test_id") en mémoire lors du traitement de la requête.