2 votes

Colonne Rows dans le Query Plan confondant

J'ai une requête MySql

 SELECT TE.company_id, 
        SUM(TE.debit- TE.credit) As summation 
 FROM Transactions T JOIN Transaction_E TE2 
      ON (T.parent_id = TE2.transaction_id) 
 JOIN Transaction_E TE 
      ON (TE.transaction_id = T.id AND TE.company_id IS NOT NULL) 
 JOIN Accounts A 
      ON (TE2.account_id=A.id AND A.deactivated_timestamp=0) 
 WHERE (TE.company_id IN (1,2)) 
   AND A.user_id=2341 GROUP BY TE.company_id;

Quand j'explique la requête, le plan de celle-ci est comme (en résumé) :

 | Select type | table | type | rows |
 -------------------------------------
 | SIMPLE      | A     | ref  | 2    |
 | SIMPLE      | TE2   | ref  | 17   |
 | SIMPLE      | T     | ref  | 1    |
 | SIMPLE      | TE    | ref  | 1    |

Mais si je fais un count(*) sur la même requête (au lieu de SUM(..) ), alors il montre qu'il y a ~40k lignes pour un company_id particulier. Ce que je ne comprends pas, c'est pourquoi le plan de requête montre si peu de lignes en cours d'analyse alors qu'il y a au moins 40 000 lignes en cours de traitement. Que représente la colonne rows dans le plan de requête ? Ne représente-t-elle pas le nombre de lignes qui sont traitées dans cette table ? Dans ce cas, il devrait y avoir au maximum 2*17*1*1 = 34 lignes ?

0voto

I_am_Batman Points 685

Le plan de requête montre simplement un jugement de haut niveau sur le nombre attendu de lignes requises par table pour atteindre le résultat final. Il doit être utilisé comme un outil pour juger de la façon dont l'optimiseur "voit" votre requête, et pour l'aider un peu, au cas où les performances de la requête seraient moins bonnes ou pourraient être améliorées.

Il est toujours possible que le plan de requête soit construit sur la base d'un instantané antérieur des statistiques, et ne doit donc pas être pris pour argent comptant, surtout lorsqu'il s'agit de cardinalité.

0voto

Rick James Points 15994

D'abord, débarrassons-nous du bug de calcul :

SELECT  TE.company_id, TE.summation
    FROM  
      ( SELECT  company_id,
                SUM(debit - credit) As summation
            FROM Transaction_E
            WHERE  company_id IN (1,2)
      ) TE
    JOIN Transactions T    ON TE.transaction_id = T.id
    JOIN Transaction_E TE2 ON T.parent_id = TE2.transaction_id
    JOIN Accounts A        ON TE2.account_id = A.id
      AND  A.deactivated_timestamp = 0
    WHERE  A.user_id = 2341;

Votre requête est probablement en train de résumer la même entreprise plusieurs fois avant de faire le GROUP BY . Ma variante évite cette inflation de l'agrégat.

Je me suis débarrassé de TE.company_id IS NOT NULL parce que c'était redondant.

Voir ce que le EXPLAIN dit à ce sujet, alors discutons de votre question sur EXPLAIN plus loin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X