2011-09-13 4 views
1

J'ai cette instruction SQL qui fonctionne mais prend beaucoup de temps à traiterPerformances SQL

J'ai une table a_log et une table de personnes. J'ai besoin de trouver la dernière activité et l'utilisateur associé pour chaque identifiant pour la personne donnée dans la table des personnes.

SELECT p.`id`, activity, appphone, appname, dateadd 
FROM people p 
LEFT JOIN a_log a 
ON p.id = a.id 
WHERE ( dateadd >= '2011/09/13 00:00' and dateadd <= '2011/09/13 23:59') 
AND (a.date_time = (SELECT MAX(a1.date_time) 
     FROM activity_log a1 
     WHERE a.id = a1.id 
     GROUP BY id) OR date_time IS NULL) 
    ORDER BY `id` desc limit 0, 100 

j'ai un index non unique sur date_time champ champ et id dans la table a_log J'ai un index primaire sur le champ identifiant et un index non unique sur le terrain dateadd chez les personnes Table

Comment puis-je obtenir un temps d'exécution plus court sur cette requête? Merci

+1

Qu'est-ce que SGBDR utilisez-vous? – JohnFx

+1

Quels SGBDR utilisez-vous et que montre le plan/journal d'exécution? – Mark

+0

J'utilise mysql – user583576

Répondre

3

Cela devrait fonctionner pour vous:

SELECT p.`id`, p.activity, p.appphone, p.appname, p.dateadd, a.* 
FROM people p 
LEFT OUTER JOIN 
(
    SELECT a.id, a.date_time, a.user 
    FROM activity_log a 
    INNER JOIN 
    (
     SELECT id, MAX(date_time) as date_time 
        FROM activity_log 
        GROUP BY id 
    ) a1 ON a.id = a1.id and a.date_time = a1.date_time 
) a ON p.id = a.id 
WHERE ( dateadd >= '2011/09/13 00:00' and dateadd <= '2011/09/13 23:59' and `agent_or_underwriter` != 'agent') 
ORDER BY p.id desc limit 0, 100 
+0

fonctionne parfaitement merci beaucoup – user583576

0

Essayez d'utiliser une table dérivée au lieu d'une sous-requête. Devrait accélérer les choses de manière significative.

SELECT p.id, activity, appphone, appname, dateadd 
FROM people p 
     LEFT JOIN a_log a 
     LEFT JOIN (
      SELECT ID, MAX(date_time) MaxDate 
      FROM activity_log 
      GROUP BY ID 
     ) a1 
      ON a.ID = a1.ID 
WHERE a.date_time IS NULL OR a.date_time = ISNULL(a1.MaxDate, a.date_time) --?? 
ORDER BY id desc limit 0, 100 
+0

merci pour l'aide – user583576

0

Vous pouvez créer une table temporaire avec un index pour la sélection dans votre "AND".

+0

merci pour l'aide – user583576

2

À un haut niveau élevé (sans connaître le schéma de vos tables, vos indices, votre RDBMS, votre structure de disque, etc ....).

Je voudrais essayer de supprimer la sous-requête soit en exécutant 2 requêtes (un pour obtenir la date maximale et l'autre pour exécuter la requête externe).

Je voudrais aussi (comme Mark mentionné), regardez le plan d'exécution (avec mysql use Explain: http://dev.mysql.com/doc/refman/5.5/en/explain-output.html), qui devrait vous mettre sur la bonne voie pour commencer à optimiser.

Si vous essayez ces deux points, vous devriez pouvoir être dans une meilleure position.

+0

merci pour la poussée dans la bonne direction – user583576

0

Est-ce que cela aide? Je ne suis pas MySQL avertis de sorte que le belwo juste très bien peut-être pas mysql compatable

SELECT p.id, a.activity, a.appphone, a.appname, a.dateadd 

FROM people p LEFT JOIN a_log a ON p.id = a.id 
       LEFT JOIN (SELECT MAX(a1.date_time) 
          FROM activity_log a1 
          WHERE a.id = a1.id 
          AND a1.dateadd >= '2011/09/13 00:00' 
          and a1.dateadd <= '2011/09/13 23:59' 
          GROUP BY id 
         ) 
          amax ON a.id = amax.id AND (a.date_time = amax.date_time or a1.date_time IS NULL) 

WHERE 1 = 1 


ORDER BY 'id' desc limit 0, 100 
+0

merci pour l'aide – user583576