2010-11-18 22 views
0

J'ai cette requête que je dois effectuer où j'ai besoin d'analyser une information de champs correspondant à un autre champ dans une autre table, puis rincer et répéter sur plusieurs tables, enfin les lignes désirées sont retournées. La question est, comment puis-je accélérer cela ... il renvoie des centaines de milliers de lignes et cela ne fonctionne pas très bien pour mon client dans leur section admin car la requête provoque un plantage.MySQL fou table croisée aide!

Voici la requête:

SELECT DISTINCT t1.CU_ship_name1, t1.CU_ship_name2, t1.CU_email 
FROM (
     SELECT CU_id, CU_ship_name1, CU_ship_name2, CU_email 
     FROM customers 
     WHERE CU_solicit=1 
     AND CU_cdate >=".$startDate." 
     AND CU_cdate <=".$endDate." 
    )AS t1 
INNER JOIN orders AS t2 ON t1.CU_id = t2.O_cid 
INNER JOIN item AS t3 ON t2.O_ref = t3.I_oref 
INNER JOIN product AS t4 ON t3.I_pid = t4.P_id 
INNER JOIN (
      SELECT C_id FROM category WHERE C_store_type =1 
      ) AS t5 ON t4.P_cat = t5.C_id 

Le tableau «clients, des « ordres », « article » tables sont mises à jour avec des dizaines de milliers de nouvelles lignes tous les mois et le « produit » reçoit atleast de un cent nouvelles lignes chaque mois.

La seule chose que je pouvais penser à faire était de créer une nouvelle table qui contient cette information (ce qui n'est pas une solution idéale), et d'ajouter un index à ces tables. Je crains l'index puisque ces tables obtiennent un si grand nombre de nouvelles données mais je suis prêt à l'essayer (peut toujours l'annuler correctement?). Cependant, je ne crois pas que l'index permettra de résoudre le problème par lui-même. MISE À JOUR: J'utilise maintenant cette requête et obtenir des résultats plus rapides, l'indexation de toutes les lignes WHERE et JOIN ON n'a pas aidé du tout ... Je n'arrive pas à comprendre pourquoi.

: Suppression des sous-requêtes

a eu un effet désastreux sur ma vitesse de recherche et de 3-4 secondes sur la requête ci-dessous à 151 avec les mêmes perameters.

SELECT DISTINCT t1.CU_ship_name1, t1.CU_ship_name2, t1.CU_email 
FROM customers AS t1 
WHERE t1.CU_solicit=1 
AND t1.CU_cdate>= 20100725000000 
AND t1.CU_cdate<= 20100801000000 
AND EXISTS(
    SELECT NULL FROM orders AS t2 
    INNER JOIN item AS t3 ON t2.O_ref = t3.I_oref 
    INNER JOIN product AS t4 ON t3.I_pid = t4.P_id 
    INNER JOIN (
     SELECT C_id 
     FROM category 
     WHERE C_store_type = 2 
    ) AS t5 ON t4.P_cat = t5.C_id 
    WHERE t1.CU_id = t2.O_cid); 

de Nevermind, je les ai changé à la normale et sans joint sous-requêtes et cette chose est soulagement après tout rapide maintenant. Voici la requête maintenant:

SELECT DISTINCT t1.CU_ship_name1, t1.CU_ship_name2, t1.CU_email 
FROM customers AS t1 
JOIN orders AS t2 ON t1.CU_id = t2.O_cid 
JOIN item AS t3 ON t2.O_ref = t3.I_oref 
JOIN product AS t4 ON t3.I_pid = t4.P_id 
JOIN category AS t5 ON t4.P_cat = t5.C_id 
WHERE t1.CU_solicit =1 
AND t1.CU_cdate >=20100425000000 
AND t1.CU_cdate <=20100801000000 
AND t5.C_store_type =2 

Répondre

2

Je vais essayer deux choses:

1) Ajouter des index sur les colonnes que vous utilisez dans les clauses ON et où

2) éliminer les sous-requêtes par réécriture les en tant que JOINs et WHERE conditions normales

Seulement une fois que vous avez fait ceux-ci et avez trouvé que vous avez toujours un problème si vous envisagez d'autres options.

Cela ressemble vraiment à une requête assez simple, autre que les sous-requêtes inutiles. Vous ne vous attendez pas à ce qu'il soit lent même avec des millions de lignes, sauf si vous n'avez pas d'index définis, vous avez trop peu de mémoire disponible pour MySQL ou vous avez très mal configuré le serveur MySQL pour les ressources disponibles.

Dix mille nouvelles lignes par mois ne sont rien. Vous mettez dans une nouvelle rangée une fois toutes les quelques minutes. Ce n'est même pas un facteur à prendre en compte pour décider quels index définir. MySQL sur un serveur bon marché peut gérer des centaines d'insertions par seconde.

1

Je voudrais indexer les colonnes dans vos critères Where ainsi que dans vos instructions ON. Les index répondront immédiatement à votre problème de plantage et ne dégraderont probablement pas vos opérations de modification de manière significative. Des dizaines de milliers de lignes chaque mois ne sont pas réellement autant de lignes - à moins que votre base de données soit sur une machine faible.

En outre, je voudrais examiner complètement les sous-requêtes. Ils ralentissent souvent les performances du serveur SQL. Vous pouvez également envisager de déplacer la requête dans une procédure stockée afin que le serveur ait la possibilité de mettre en cache son plan d'exécution.

+0

Merci, j'ai indexé les colonnes ON et WHERE mais cela n'a pas fait de différence notable, d'autres suggestions? En outre, enlever le moi m'a pris de 6-9seconds sur mes paramètres de test à 151secondes ... soo il est allé complètement l'autre manière aussi loin que les sous-requêtes vont maintenant im confondu hah. – BinarySolo00100

+0

Très bien, j'ai une note de côté que je pourrais vous connaître d'un travail que vous m'avez embauché à San Diego @ SMS, si c'est vous, j'espère que vous allez bien, Tanner Smith. – BinarySolo00100

+0

Woah - quoi de neuf Tanner! Comment êtes vous aller? Peut-être que nous devrions prendre ce chat pour fb ou e-mail :) Quelle était la combinaison gagnante de correctifs? –