2012-12-06 9 views
-1

Je tablesrequête est très lent

table1

epid  etid  id   EValue  reqdate 
----------- ----------- ----------- ------------ ---------- 
15   1   1   498925307069 2012-01-01 
185   1   2   A5973FC43CE3 2012-04-04 
186   1   2   44C6A4B776A2 2012-04-05 
205   1   2   7A0ED3F1DA13 2012-09-19 
206   1   2   77771D65F9C4 2012-09-19 
207   1   2   AD74A4AA41BD 2012-09-19 
208   1   2   9595ABE5A0C8 2012-09-19 
209   1   2   7611D2FB395B 2012-09-19 
210   1   2   04A510D6067A 2012-09-19 
211   1   2   24D43EC268F8 2012-09-19 

table2

PEId  Id   EPId 
----------- ----------- ----------- 
43   9   15 
44   10   15 
45   11   15 
46   12   15 
47   13   15 
48   14   15 
49   15   15 
50   16   15 
51   17   15 
52   18   15 

table3

PLId  PEId  Id   ToPayId 
----------- ----------- ----------- ----------- 
71   43   9   1 
72   43   9   2 
73   44   10   1 
74   44   10   2 
75   45   11   1 
76   45   11   2 
77   46   12   1 
78   46   12   2 
79   47   13   1 
80   47   13   2 

Je veux obtenir un identifiant dont le nombre est inférieur à 8 dans le tableau 3 et ordre par peid dans le tableau 2,

J'ai écrit requête

SELECT Top 1 ToPayId FROM 
(
    SELECT Count(pl.ToPayId) C, pl.ToPayId 
    FROM table3 pl 
    INNER JOIN table2 pe ON pl.peid = pe.peid 
    INNER JOIN table1 e ON pe.epid = e.epid 
    WHERE e.EtId=1 GROUP BY pl.ToPayId 
) As T 
INNER JOIN table2 p ON T.ToPayId= p.Id 
WHERE C < 8 ORDER BY p.PEId ASC 

Cette requête exécute plus de 1000 fois dans la procédure stockée dépend des entrées-type de table défini par l'utilisateur à l'aide en condition.

Mais c'est très lent car nous avons des millions d'entrées dans chaque table.

Quelqu'un peut-il suggérer une meilleure question concernant ce qui précède?

+0

Y a-t-il des index? Peut-être pourriez-vous nous montrer le DDL pour les tables. – AakashM

+0

Pour référence future, "lakh" est une unité qui signifie 100 000. –

+0

Oui, j'ai créé l'index non-crissé sur etid (table1), topayid, peid (table3) –

Répondre

0

peut-être essayer avec la clause ayant pour se débarrasser de la de select

select table2.id as due 
     from table3 inner join table2 on table2.PEId=table3.PEId... 
     group by ... 
     having count(due) <8 
     order by ... 

-> vous avez une colonne redondante Id dans table3: semble assez inutile que le couple peid et Id semble unique, enlever si et réduire la taille de la table 3 de 25% d'où l'amélioration des performances de db

+0

La structure de la table est correcte selon la logique métier et elle ne peut pas être modifiée maintenant. Et j'essaie votre requête suggérée (ayant), mais il ne contient pas table1. La table1 est requise pour vérifier la valeur etid. –

+1

c'était un exemple, si je fais votre travail, je pourrais aussi bien obtenir votre salaire!? de toute façon l'avoir est la bonne manière d'aller; NB: la redondance est coûteuse et il n'y a pas de logique métier que je connaisse de ce défenseur du gaspillage de ressources – mikakun

+0

ok, c'est bon, ça marche. Merci –

0

Will .. puisque vous n'avez pas fourni suffisamment de données d'échantillon et je ne suis pas sûr de ce que votre logique métier est exactement. Alors que je peux juste modifier le code en aveugle.

SELECT ToPayId 
FROM (

    SELECT TOP 1 Count(pl.ToPayId) C, pl.ToPayId, pe.PEId 
    FROM table3 as pl 
     INNER JOIN table2 as pe ON pl.peid = pe.peid AND pl.ToPayId = pe.Id 
     INNER JOIN table1 e ON pe.epid = e.epid 
    WHERE e.EtId=1 
    GROUP BY pl.ToPayId, pe.PEId 
    HAVING Count(pl.ToPayId) < 8 
    ORDER BY pe.PEId ASC  

) AS T 
+0

ne peut pas trouver pourquoi, mais la requête ne renvoie rien. et comme vous incluez PEId dans le groupe, il retournera le premier enregistrement de Db (toutes les lignes sinon top 1) –

+0

J'ai essayé votre code et il ne retourne rien. Je pense que cela peut être plus utile si vous pouvez expliquer la logique métier plus clairement et fournir plus de données d'échantillons. –