2008-12-08 5 views
1

Ok, je ne suis pas grand dans MySQL, mais je connais un index me aider ici, mais je l'ai fait un peu Enfichage et ne peut pas trouver un pour vous aider ...aide avec un indice

Quelqu'un a une idée?

explain 
select `users_usr`.`id_usr` AS `id_usr`, 
`users_usr`.`firstname_usr` AS `firstname_usr`, 
`users_usr`.`lastname_usr` AS `lastname_usr`,`users_usr`.`social_usr` AS `social_usr`,`users_usr`.`address1_usr` AS `address1_usr`, 
`users_usr`.`address2_usr` AS `address2_usr`,`users_usr`.`city_usr` AS `city_usr`,`users_usr`.`state_usr` AS `state_usr`,`users_usr`.`zip_usr` AS `zip_usr`, 
`users_usr`.`email_usr` AS `email_usr`,`credit_acc`.`given_credit_acc` AS `given_credit_acc`,`credit_acc`.`credit_used_acc` AS `credit_used_acc`, 
`credit_acc`.`date_established_acc` AS `date_established_acc`,`credit_acc`.`type_acc` AS `type_acc`,`credit_acc`.`bureau_status_acc` AS `bureau_status_acc`, 
sum((`credit_balance`.`debit_acc` - `credit_balance`.`credit_acc`)) AS `balance` 



from (((`users_usr` 
left join `credit_acc` on((`users_usr`.`id_usr` = `credit_acc`.`uid_usr`))) 
left join `cfc_cfc` on((`credit_acc`.`id_cfc` = `cfc_cfc`.`id_cfc`))) 
join `credit_acc` `credit_balance` on((`credit_balance`.`credit_used_acc` = `credit_acc`.`id_acc`))) 

where ((`credit_acc`.`type_acc` = _latin1'init') 
and (`credit_acc`.`status_acc` = _latin1'active') 
and (`credit_acc`.`linetype_acc` = _latin1'personal')) 

group by `credit_balance`.`credit_used_acc` order by `users_usr`.`id_usr` 

Ça me donne

id select_type table   type possible_keys      key    key_len ref         rows Extra       
------ ----------- -------------- ------ ----------------------------------- --------------- ------- --------------------------------- ------ ------------------------------- 
    1 SIMPLE  credit_balance index credit_used_acc,cash_report_index credit_used_acc 40  (NULL)        14959 Using temporary; Using filesort 
    1 SIMPLE  credit_acc  eq_ref PRIMARY,type_acc,type_acc_2,uid_usr PRIMARY   8  cc.credit_balance.credit_used_acc  1 Using where      
    1 SIMPLE  cfc_cfc   eq_ref PRIMARY        PRIMARY   4  cc.credit_acc.id_cfc     1 Using index      
    1 SIMPLE  users_usr  eq_ref PRIMARY,id_usr      PRIMARY   4  cc.credit_acc.uid_usr     1 



Table  Non_unique Key_name   Seq_in_index Column_name    Collation Cardinality Sub_part Packed Null Index_type Comment 
---------- ---------- ----------------- ------------ ----------------------- --------- ----------- -------- ------ ------ ---------- ------- 
credit_acc   0 PRIMARY      1 id_acc     A    14016 (NULL) (NULL)   BTREE    
credit_acc   1 type_acc      1 type_acc     A     11 (NULL) (NULL) YES  BTREE    
credit_acc   1 type_acc      2 date_acc     A    14016 (NULL) (NULL) YES  BTREE    
credit_acc   1 type_acc      3 affiliate_aff   A    14016 (NULL) (NULL) YES  BTREE    
credit_acc   1 type_acc_2     1 type_acc     A     11 (NULL) (NULL) YES  BTREE    
credit_acc   1 type_acc_2     2 date_acc     A    14016 (NULL) (NULL) YES  BTREE    
credit_acc   1 type_acc_2     3 complete_acc    A    14016 (NULL) (NULL) YES  BTREE    
credit_acc   1 type_acc_2     4 commission_refunded_acc A    14016 (NULL) (NULL) YES  BTREE    
credit_acc   1 credit_used_acc    1 credit_used_acc   A    14016 (NULL) (NULL) YES  BTREE    
credit_acc   1 credit_used_acc    2 id_acc     A    14016 (NULL) (NULL)   BTREE    
credit_acc   1 credit_used_acc    3 type_acc     A    14016 (NULL) (NULL) YES  BTREE    
credit_acc   1 uid_usr      1 uid_usr     A     7008 (NULL) (NULL) YES  BTREE    
credit_acc   1 cash_report_index    1 credit_used_acc   A     7008 (NULL) (NULL) YES  BTREE    
credit_acc   1 cash_report_index    2 type_acc     A    14016 (NULL) (NULL) YES  BTREE    
credit_acc   1 cash_report_index    3 date_established_acc  A    14016 (NULL) (NULL) YES  BTREE    
+0

quoi avec la dernière jointure? Pas vu ça avant! – benlumley

Répondre

0

Votre EXPLAIN montre que vous avez déjà des indices qui pourraient être utile, mais le moteur de recherche a décidé de ne pas les utiliser.

http://dev.mysql.com/doc/refman/5.0/en/using-explain.html dit:

En utilisant temporaire

Pour résoudre la requête, MySQL doit créer une table temporaire pour contenir le résultat . Cela se produit généralement si la requête contient des clauses GROUP BY et ORDER BY qui répertorient les colonnes différemment.

Votre requête comprend:

GROUP BY `credit_balance`.`credit_used_acc` 
ORDER BY `users_usr`.`id_usr` 

Vous nommez des colonnes différentes dans ces deux clauses, donc cela signifie que la requête nécessite une table temporaire et trie ses résultats sur le disque. L'E/S disque est l'ennemi juré des performances SQL. Ceci est probablement plus préjudiciable aux performances que vous pouvez compenser en appliquant un index.

Donc, je suggère d'essayer de supprimer la clause ORDER BY et de voir si elle se débarrasse du commentaire "using temporary".

edit Okay, j'ai fait quelques tests de plus et j'ai regardé de plus près les défauts de votre table.

Je pense que vous avez beaucoup d'index redondants et non applicables à cette requête en cours. Il se peut que les index soient utiles à une autre requête, ou qu'ils ne soient que des restes de vos expériences.

Une remarque est que votre jointure à cfc_cfc est inutile mais je vois de votre commentaire que vous l'avez retiré. Cependant, cela ne semble pas corriger le rapport EXPLAIN.

Une autre observation est que votre LEFT JOIN est inutile; il peut s'agir d'un INNER JOIN car vous avez des conditions dans la clause WHERE pour ces colonnes. Cela ne sert à rien d'être une jointure externe, et les jointures externes ont tendance à être plus lentes.

Les index peuvent être utiles pour les colonnes que vous utilisez dans les conditions de jointure, dans les restrictions de ligne ou dans les clauses GROUP BY ou ORDER BY. MySQL ne peut pas utiliser plus d'un index par table dans une requête donnée, il est donc logique de définir des index composés. Mais vous devez définir l'index sur les colonnes utilisées dans la requête. Si vous utilisez uniquement les colonnes 2 et 3 d'un index à trois colonnes (c'est-à-dire pas la première colonne de l'index), l'index est inefficace.

Bien sûr il y a des indices créés implicitement pour toutes les principales contraintes clés et à l'étranger primaire, mais voici le seul indice supplémentaire que je créé:

KEY columns_used_in_query (uid_usr, type_acc, status_acc, linetype_acc), 

Il ne devrait pas d'importance au plan d'optimisation si vous mettez vos conditions dans la clause WHERE ou la condition de jointure, tant qu'ils ne font pas partie des conditions d'une jointure externe. Mais je remarque que toutes choses étant égales par ailleurs, l'optimiseur semble choisir un index en fonction de celui que vous définissez en premier!

Je n'ai toujours pas éliminé la table temporaire & fileort commentort dans le rapport EXPLAIN, mais je pense que ces changements vont accélérer la requête.

+0

bien, j'ai tué l'ordre, et il n'a pas changé la requête. Cependant, j'ai créé un index sur JUST status_acc, et il m'a tiré de 100% des lignes examinées, à environ 20%, mais j'ai toujours un temp et filesort. – bbutle01

0

Rétractez une partie de cela et recommencez.

Voici mon interprétation de votre requête.

uu.select uu.id_usr,
uu.firstname_usr,
uu.lastname_usr,
uu.social_usr,
uu.address1_usr,
uu.address2_usr,
uu.city_usr,
uu .state_usr,
uu.zip_usr,
uu.email_usr,
ca.given_credit_acc,
ca.credit_used_acc,
ca.date_established_acc,
ca.type_acc,
ca.bureau_status_acc,
somme (cb.debit_acc - cb.credit_acc) AS balance

de users_usr AS uu

gauche rejoindre credit_acc AS ca sur uu.id_usr = ca.uid_usr

rejoindre credit_acc Cb sur ca.credit_used_acc = ca.id_acc

où ca.type_acc = ' INIT
et ca.status_acc = 'actif'
et ca.linetype_acc = 'groupe personnel'

par cb.credit_used_acc
commande par uu.id_usr

+0

a sorti la table cfc_cfc, j'ai oublié que je ne l'utilisais plus, je n'ai pas beaucoup aidé car c'était seulement en train de regarder une rangée là de toute façon, mais il vaut mieux être plus propre. – bbutle01

0

Votre requête (la partie optimisable à la s'associe, wheres, des groupes et des sortes) peuvent être simplifiées pour:

SELECT
uu.select uu.id_usr,
ca.given_credit_acc,
ca.c redit_used_acc,
ca.type_acc,
somme (cb.debit_acc - cb.credit_acc) AS balance

DE
users_usr AS uu

LEFT JOIN
credit_acc AS ca sur uu.id_usr = ca.uid_usr
ET ca.type_acc = 'init'
ET ca.status_acc = 'actif'
ET ca.linetype_acc = 'personnel'
- credit_acc a besoin d'un index sur uid_usr + type_acc _ status_acc

JOIN
credit_acc Cb sur ca.credit_used_acc = ca.id_acc
- credit_acc a besoin d'un index sur credit_used_acc

GROUP BY cb.credit_used_acc
ORDER BY uu.id_usr

Notez que je pris la WHERE clause et déplacé dans le JOIN - MySQL semble aimer ce genre d'ajustement.

Notez les commentaires sur les index. Voyez si vous pouvez obtenir cette simplification pour travailler (et optimiser), puis rajouter les autres champs.

Qu'en pensez-vous, Bill?