2011-10-02 5 views
4

Je veux optimiser cette requête (puisque les sous-requêtes ne sont pas rapides en général), mais je suis perdu car je ne peux pas réécrire cela en utilisant des jointures qui seront meilleures pour la performance.MySQL optimiser les sous-requêtes

SELECT id, company, street, number, number_addition, postalcode, telephone 
FROM clients 
    WHERE (postalcode BETWEEN '1000' AND '9000') AND street = (
     SELECT DISTINCT street FROM clients WHERE (postalcode BETWEEN '1000' AND '9000') AND postalcode <= (
      SELECT MIN(postalcode) FROM clients WHERE street = 'Main Street' AND  (postalcode BETWEEN '1000' AND '9000')) 
     ORDER BY postalcode DESC LIMIT 1, 1) 
ORDER BY postalcode DESC, street DESC, number DESC, number_addition DESC, telephone DESC 
LIMIT 1 

Merci pour votre temps les gars.

+0

Cette requête est-elle vraiment lente? Ne pas optimiser au hasard. Activez * slow_query_log * dans votre serveur MySQL. Cela enregistre les requêtes qui prennent plus de * long_query_time * dans votre fichier * slow_query_log_file *. –

Répondre

1

SELECT DISTINCT street ORDER BY postalcode n'a pas de sens (et je pense n'est pas SQL valide ANSI), à moins que postalcode est fonctionnellement dépendant street -qui, je ne pense pas que ce soit, que votre rendez-vous le plus bas postalcode-on- La sous-sélection interne de Main-Street n'aurait pas de sens si c'était le cas. MySQL vous laissera s'en tirer mais les résultats seront incohérents. Qu'essayez-vous de dire ici?

Je ne pense pas que cela devrait être particulièrement lent puisque ce que vous avez n'est pas une sous-requête dépendante; les sous-requêtes ne sont exécutées qu'une seule fois et pas de manière répétée pour chaque ligne externe. Vous pouvez le réécrire en trois requêtes distinctes-

  1. obtenir le code postal le plus bas sur Main Street;
  2. obtenir la rue avec le deuxième code postal le plus bas inférieur à (1) (incohérent);
  3. obtenir des détails sur les clients sur la rue (2).

sans différence d'exécution. (En effet, il pourrait être préférable de le faire pour plus de clarté.)

Vous pouvez réécrire ces derniers comme les jointures, en utilisant l'auto-gauche-joint sur-moins-que-est nul pour obtenir les minima/maxima, mais je ne pense pas que vous y gagneriez quoi que ce soit pour cet exemple et cela deviendrait très salissant étant donné les deux niveaux d'adhésion et la deuxième exigence la plus élevée. Cette requête est-elle particulièrement lente en pratique? À quoi ressemble le EXPLAIN? Avez-vous indexé postalcode et street?

+0

SÉLECTIONNER DISTINCT rue ORDER BY postalcode - la chose est que j'ai une table de clients et je veux obtenir toutes les rues dans ce tableau. Chaque rue peut avoir plusieurs codes postaux, donc je veux choisir la valeur la plus basse du code postal et ordonner les rues par ceci. – Joseph

+0

Je ne pouvais pas encore tester cela en production, mais puisque c'est une requête qui fonctionne sur l'interface de l'application (rarement), j'ai pensé que ce serait une bonne idée d'accélérer ça, mais si vous pensez que c'est OK! Attendez-vous comment cela va fonctionner dans la production. BTW à la fois le code postal et la rue sont indexés. Merci pour votre temps. – Joseph

+0

Vous ne commandez pas les rues par le code postal minimum, vous commandez par un code postal aléatoire par rue. D'autres DB signaleront cela comme une erreur, car c'est généralement une erreur. Essayez 'SELECT rue ... GROUPE PAR rue ORDER BY MIN (code postal)'. – bobince

Questions connexes