2010-12-16 198 views
2

à Derby et/ou MySQL, je me demande sur les performances de:par rapport joint corrélative existe des sous-requêtes

select c0.documentid from contentblob as c0 where c0.documentid > ? 
    and c0.blobid = ? 
    and exists (select * from contentblob c1 where c1.documentid = c0.documentid 
       and c1.blobid = ?) 
    order by c0.documentid 

Notez que des valeurs différentes seront fournies pour les deux comparaisons blobid. Ce que fait cette requête est de retourner deux fois les identifiants qui apparaissent dans la table (au moins): une fois avec blobid1 et une fois avec blobid2.

par rapport à l'auto-jointure équivalente,

en supposant, bien sûr, les indices sur les colonnes de documentid et blobid de la table contentblob.

Dans le cas où cela n'est pas clair, le schéma correspondant est une table avec deux colonnes varchar, documentid et blobid. Ils sont composés pour former la clé primaire.

S'il n'y a rien pour cela mais pour se renseigner sur l'analyseur de requête dans la base de données, je vais le faire.

Répondre

1

En général, les sous-requêtes corrélées sont plus chers que les jointures même auto-jointures externes, bien que dans ce cas, tout ce que vous avez besoin est une auto-jointure interne régulière:

SELECT c0.documentid 
    FROM contentblob AS c0 
    JOIN contentblob AS c1 ON c1.documentid = c0.documentid 
WHERE c0.documentid > ? 
    AND c0.blobid = ? 
    AND c1.blobid = ? 
    AND c0.blobid < c1.blobid 
ORDER BY c0.documentid 

La dernière condition évite de voir deux des entrées pour une paire de lignes avec le même ID de document et les valeurs d'ID de blob pertinentes; sans cela, vous verriez l'ID de document deux fois, une fois pour c0.blobid = v1 et une fois pour c0.blobid = v2.

Vous pouvez déplacer la condition c1.blobid dans la clause ON, mais l'optimiseur devrait le faire pour vous de toute façon. Vérifiez également que votre optimiseur utilise un index approprié. Il n'est pas tout à fait clair quel serait cet index (mais je pense qu'un index avec blobid comme la colonne principale fonctionnerait probablement mieux), mais si les tables sont grandes et l'optimiseur utilise un balayage séquentiel de la table, vous avez des problèmes .

0

Je pense que la jointure gauche serait plus claire

select c0.documentid from contentblob as c0 where c0.documentid > ? 
    and c0.blobid = ? 
    left join contentblob c1 on c0.documentid = c1.documentid 
     and c1.blobid = ? 
    order by c0.documentid 

Kilométrage varie pour les différents moteurs de base de données, et, également varier selon la taille des tables, index cardinalité etc., mais mon sentiment est la jointure exécuterait mieux .

+0

Voir la modification pour ce que j'espère va clarifier. Deux blobids différents sont impliqués. – bmargulies

+0

Ah! Aurait dû repérer cela - changé la réponse en conséquence! –

+0

J'ai toujours pensé que les instructions EXISTS() étaient plus claires à lire et qu'elles ne créaient pas de doublons potentiels dans le jeu de résultats. –