2009-05-14 6 views
0

J'ai une requête particulièrement lente en raison de la grande quantité d'informations réunies. Cependant, j'ai besoin d'ajouter une clause where sous la forme d'id (sélectionnez l'ID de la table).SQL (any) Demande d'informations sur une optimisation de requête

Je veux savoir s'il y a un gain de ce qui suit, et plus pressant, il donnera même les résultats souhaités.

select a.* from a where a.id in (select id from b where b.id = a.id) 

comme alternative à:

select a.* from a where a.id in (select id from b) 

Mise à jour: MySQL ne peut pas être désolé plus spécifique d'une table est effectivement une jointure entre 7 tables différentes. utilisation de * est des exemples

Edit, b ne soit pas sélectionné

+1

Note: elles sont simplifiées, c'est en fait une jointure entre 7 tables de commande/client/paiement différentes – Louis

+0

ouais, je me demande pourquoi une jointure entre 7 tables différentes pourrait être lente :-) – lothar

+0

Pourquoi serait-ce lent à cause de les 7 tables? ce n'est rien;) – Louis

Répondre

2

Votre question portait sur la différence entre ces deux:

select a.* from a where a.id in (select id from b where b.id = a.id) 

select a.* from a where a.id in (select id from b) 

La première est une sous-requête corrélée. Il se peut que MySQL exécute la sous-requête pour chaque ligne de a.

Cette dernière est une sous-requête non corrélée. MySQL devrait être capable de l'exécuter une fois et mettre en cache les résultats pour comparaison avec chaque ligne de a.

Je voudrais utiliser ce dernier.

+0

Merci. Cela explique certaines choses. – Louis

0

YMMV, mais je l'ai souvent trouvé avec exists au lieu de requêtes fait courir plus vite.

SELECT a.* FROM a WHERE EXISTS (SELECT 1 FROM b WHERE b.id = a.id) 

Bien sûr, sans voir le reste de la requête et le contexte, cela peut ne pas accélérer la requête. JOINING peut être une option préférable, mais si a.id apparaît plus d'une fois dans la colonne id de b, vous devrez lancer DISTINCT là-bas, et vous risquez de reculer en termes d'optimisation.

+0

Qu'est-ce qui vous fait penser que cela fonctionnera plus vite? – Andomar

+0

Distinct serait nécessaire – Louis

0

Je n'utiliserais jamais une sous-requête comme celle-ci. Une jointure serait beaucoup plus rapide.

select a.* 
from a 
join b on a.id = b.id 

Bien sûr, ne pas utiliser select * soit (surtout jamais l'utiliser lorsque vous faites une jointure au moins un champ est répété) et gaspille les ressources du réseau pour envoyer des données unnneeded.

+0

Qu'est-ce qui vous fait penser que cela fonctionnera plus vite? – Andomar

+0

Joindre serait plus rapide, @ * utilisation, l'exemple a été simplifié. – Louis

+0

Le plan d'exécution est le même et cet exemple présente un enregistrement en double potentiel en fonction de la structure de b. – JeffO

0

Avez-vous regardé le plan d'exécution?

Comment probablement au sujet

select a.* 
from a 
inner join b 
on a.id = b.id 

les champs d'identification sont les clés primaires?

+0

id sont des clés/indexées – Louis

2

Les deux requêtes que vous énumérez sont l'équivalent de:

select a.* 
from a 
inner join b on b.id = a.id 

Presque tous les optimiseurs vont les exécuter de la même manière.

Vous pouvez publier un plan d'exécution réel, et quelqu'un ici pourrait vous donner un moyen de l'accélérer. Cela aide si vous spécifiez quel serveur de base de données vous utilisez.

+0

mysql innodb, ne peut pas poster plan d'exécution désolé. – Louis

+0

le titre dit sql (any) parce que c'est une question théorique, – Louis

+1

Lou a indiqué que b pourrait avoir des ID en double, donc une jointure ne produirait pas les mêmes résultats. – JeffO

0
Select a.* from a 
inner join (Select distinct id from b) c 
on a.ID = c.AssetID 

J'ai essayé toutes les 3 versions et elles ont fonctionné à peu près la même chose. Le plan d'exécution était le même (jointure interne, IN (avec et sans clause where dans la sous-requête), Existe)

Puisque vous ne sélectionnez aucun autre champ de B, je préfère utiliser le champ Où IN (Select ... Tout le monde regarde la requête et sait ce que vous essayez de faire (Montrer seulement dans un si dans b.).

+0

Mon explication donne des types de sélection simples sur tout pour la jointure, et pour le 'dans select' il donne des primaires sur toutes les tables puis sous-requête dépendante. Join semble être l'option la plus rapide même en utilisant distinct. – Louis

0

votre problème est plus probable dans les sept tables dans « un »

font la table FROM contiennent le « a.id » faire la prochaine jointure: jointure interne b sur a.id = b.id

puis rejoignez les six autres tables.

vous avez vraiment besoin de montrer toute la requête, la liste de tous les index, et le nombre de lignes approximatives de chaque table si vous voulez une aide réelle

+0

Non voir, je ne demande que la différence entre les deux montré dans ma question. la partie 'a' n'est pas cassée, les index sont correctement utilisés. Il n'est pas lent dans le sens où la requête pourrait être optimisée plus lente car c'est un jeu de résultats énorme. La liste de db schema n'est pas importante ici, elle est réduite aux parties qui m'intéressent. – Louis

Questions connexes