12
votes

Gauche Rejoignez plus vite ou interne Joindre plus vite?

Alors ... lequel est plus rapide (la valeur null n'est pas un problème) et sont indexés. XXX PRE>

Utilisation de jointures gauche: P>

Query (0.2693sec) :
    EXPLAIN EXTENDED SELECT * 
    FROM friend_events, zcms_users, user_events, 
    EVENTS WHERE friend_events.userid = '13006'
    AND friend_events.state =0
    AND UNIX_TIMESTAMP( friend_events.t ) >=1258923485
    AND friend_events.xid = user_events.id
    AND user_events.eid = events.eid
    AND events.active =1
    AND zcms_users.id = user_events.userid

EXPLAIN

    id select_type table type possible_keys key key_len ref rows Extra 
    1 SIMPLE zcms_users ALL PRIMARY NULL NULL NULL 43082 
    1 SIMPLE user_events ref PRIMARY,eid,userid userid 4 zcms_users.id 1 
    1 SIMPLE events eq_ref PRIMARY,active PRIMARY4 user_events.eid 1 Using where
    1 SIMPLE friend_events eq_ref PRIMARY PRIMARY 8 user_events.id,const 1 Using where



    LEFTJOIN QUERY: (0.0393 sec)

    EXPLAIN EXTENDED SELECT * 
    FROM `friend_events` 
    LEFT JOIN `user_events` ON user_events.id = friend_events.xid
    LEFT JOIN `events` ON user_events.eid = events.eid
    LEFT JOIN `zcms_users` ON user_events.userid = zcms_users.id
    WHERE (
    events.active =1
    )
    AND (
    friend_events.userid = '13006'
    )
    AND (
    friend_events.state =0
    )
    AND (
    UNIX_TIMESTAMP( friend_events.t ) >=1258923485
    )


EXPLAIN
    id select_type table type possible_keys key key_len ref rows Extra 
    1 SIMPLE friend_events ALL PRIMARY NULL NULL NULL 53113 Using where
    1 SIMPLE user_events eq_ref PRIMARY,eid PRIMARY 4 friend_events.xid 1 Using where
    1 SIMPLE zcms_users eq_ref PRIMARY PRIMARY 4 user_events.userid 1 
    1 SIMPLE events eq_ref PRIMARY,active PRIMARY 4 user_events.eid 1 Using where


11 commentaires

Pourquoi ne les dirigez-vous pas les deux et dites-nous ce qui est plus rapide?


Cette question devrait être repharmée: "Comment puis-je comprendre quelle requête fonctionne plus vite?"


Ces événements renvoient-ils le même ensemble de résultats? (colonnes, pas rangées)


@JMD Je ne vois pas pourquoi ils retourneraient différentes colonnes. Contrairement, il existe une forte possibilité de renvoyer différentes lignes.


@Nathan: L'exemple de jointure gauche retournerait des rangées d'un où il n'y avait pas de lignes en B et / ou C - les colonnes B / C seraient nuls. Donc, vous auriez plus de colonnes dans une jointure de gauche.


@OMG Poneys, n'auriez-vous pas alors la même quantité de colonnes, mais avec des valeurs nuls dans ces colonnes?


@Nathan: Vous êtes correct, je pense que JMD a juste eu des choses mélangées.


En fait, je n'ai pas besoin d'avoir des colonnes NULL B / C.


@Murvinlai: Ensuite, vous ne devriez pas utiliser les jointures gauche, mais votre question était de toute façon universitaire.


@Murvinlai - merci d'avoir publié vos plans de requête - j'ai mis à jour ma réponse; S'il vous plaît, jetez un oeil.


Allez, il ne peut pas y avoir 10 fois de différence dans ces requêtes, il doit être mis en cache des tables et des index qui donnaient cette grande différence de temps. Pourquoi les gens font-ils attention à cette période?


4 Réponses :


9
votes

Cela dépend; courir les deux pour le savoir; puis exécutez un "expliquant" sélectionnez 'pour une explication.

La différence de performance réelle peut aller de "pratiquement inexistante" à "assez significative" en fonction du nombre de lignes en A avec ID = '12345' n'ont aucun enregistrement correspondant en B et C.

mise à jour (basé sur des plans de requête postés)

Lorsque vous utilisez une jonction intérieure, cela n'a pas d'importance (résultats-sage, pas de performance) Quelle table pour commencer, alors Optimizer tente de choisir celui qui pense jouer le mieux. Il semble que vous disposiez d'index sur toutes les colonnes PK / FK appropriées et que vous n'avez pas d'index sur ami_events.userid ou il y a trop d'enregistrements avec userid = '13006' Et ce n'est pas utilisé; Soit Optimizer, optimiseur choisit la table avec moins de lignes comme "base" - dans ce cas, c'est zcms_user . .

Lorsque vous utilisez la jointure gauche, il fait matière (résultats-sages) qui commencent par; Ainsi, ami_events est choisi. Maintenant pourquoi il faut moins de temps de cette façon, je ne suis pas tout à fait sûr; Je suppose que ami_events.userid condition aide. Si vous deviez ajouter un index (est-ce vraiment varchar, BTW? Pas numérique?) À ce sujet, votre jointure intérieure pourrait se comporter différemment (et devenir plus rapide).


2 commentaires

Je l'ai couru. Il semble que l'Inner One est bien plus lent. Mais n'est-ce pas que l'intérieur devrait être bette rhana à gauche?


Pouvez-vous poster les résultats de "Expliquer la sélection" des deux requêtes?



2
votes

Utilisez Expliquez pour voir le plan de requête. C'est probablement le même plan pour les deux cas, alors je doute que cela fait beaucoup de différence, en supposant qu'il n'y ait pas de rangées qui ne correspondent pas. Mais ce sont deux requêtes différentes, donc il n'a pas vraiment de sens de les comparer - vous devriez simplement utiliser le bon.

Pourquoi ne pas utiliser le mot-clé "REJOIGNE INTERNE" au lieu de "JOIN DE GAUCHE"?


0 commentaires

6
votes

La join interne doit effectuer une vérification supplémentaire pour supprimer tous les enregistrements d'A qui ne disposent pas d'enregistrements correspondants dans B et C. Selon le nombre d'enregistrements revenus initialement de celui qui pourrait avoir un impact.


0 commentaires

2
votes

rejoindre gauche affiche toutes les données de A et uniquement des données de B / C uniquement si la condition est vraie. En ce qui concerne interne rejoindre , il doit faire une vérification supplémentaire sur les tables . Donc, je suppose que cela explique pourquoi rejoindre est plus rapide.


0 commentaires