2012-11-06 2 views
6

J'ai un problème sérieux avec MySQL (innoDB) 5.0.Vérification de la plage Mysql au lieu de l'utilisation de l'index sur la jointure interne

Une requête SQL très simple est exécutée avec un plan de requête très inattendu.

La requête:

SELECT 
SQL_NO_CACHE 
mbCategory.* 

FROM 
MBCategory mbCategory 

INNER JOIN ResourcePermission as rp 
    ON rp.primKey = mbCategory.categoryId 

where mbCategory.groupId = 12345 AND mbCategory.parentCategoryId = 0 
limit 20; 

MBCategory - contient 216583 lignes

ResourcePermission - contient 3098354 lignes.

Dans MBCategory j'ai plusieurs index (ordre des colonnes comme dans l'index):

Primary (categoryId) 
A (groupId,parentCategoryId,categoryId) 
B (groupId,parentCategoryId) 

En ResourcePermission j'ai plusieurs index (ordre des colonnes comme dans l'index):

Primary - on some column 
A (primKey). 

Quand je regarder dans le plan de requête Mysql change la séquence des tables et sélectionne les lignes de ResourcePermission au début, puis il rejoint la table MBCategory (idée folle) et cela prend des âges. J'ai donc ajouté STRAIGHT_JOIN pour forcer le moteur InnoDB utiliser la séquence de table correcte:

SELECT 

STRAIGHT_JOIN SQL_NO_CACHE 
mbCategory.* 

FROM 
MBCategory 
mbCategory 

INNER JOIN ResourcePermission as rp 
    ON rp.primKey = mbCategory.categoryId 

where mbCategory.groupId = 12345 AND mbCategory.parentCategoryId = 0 
limit 20; 

Mais ici le deuxième problème materialzie: Dans mon mysql avis devrait utiliser index A (primKey) sur la jointure opération au lieu qu'il effectue Range vérifié pour chaque enregistrement (carte d'index: 0x400) et il prend encore des âges! L'index de forçage n'aide pas, mysql effectue toujours la vérification de la plage pour chaque enregistrement.

Il n'y a que 23 lignes dans la catégorie MB remplissant les critères, et après la jointure, il n'y a que 75 lignes. Comment puis-je faire mysql pour choisir l'index correct sur cette opération?

+0

Je pense que MySQL ne peut pas déterminer directement combien de lignes il doit lire pour trouver 20 lignes correspondantes; il choisit donc la plus grande table pour 20 matchs puis effectue la jointure interne. Que se passe-t-il si vous supprimez la limite? –

+0

La suppression de la limite ne change rien. J'ai simplement besoin de mysql pour utiliser l'index correct et non le contrôle de plage –

Répondre

23

Ok, problème élémentaire. Je me dois une bière. Le système que je suis en train de mettre au point n'est pas un système que j'ai développé - ma gestion m'a assigné pour améliorer les performances (l'équipe originall n'a pas de connaissances sur ce sujet).

Après semaines de frais d'amélioration des requêtes SQL, des index, nombre de requêtes sql qui sont exécutées par l'application, je n'ai pas vérifié l'une des choses les plus importantes dans ce cas !!

LES TYPES DE COLONNES SONT DIFFÉRENTS!

Le développeur qui a écrit que le type de code devrait obtenir un gros TALK.

Merci pour votre aide!

+0

Il est à noter que MySQL 5.7 améliore cette situation, où une 'plage dynamique' sera supportée. S'il vous plaît voir cet article de blog: http://mysqlserverteam.com/dynamic-range-access-and-recent-changes/ (qui liens à ici.) –

+1

Je vous dois également une bière –

+1

Très utile, merci pour cet aperçu – udog

Questions connexes