Question

Notre environnement: Drupal + MySQL

L'examen du journal de requête indique que la requête suivante, provenant de la fonction node_load de base Drupal prend beaucoup de temps.

EXPLIQUER sur la requête node_load révèle que l'indice n'est pas utilisé sur la table USER.

mysql> explain SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, 
    n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title, 
    r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data 
FROM xyz_node n 
INNER JOIN xyz_users u ON n.uid = u.uid 
INNER JOIN xyz_node_revisions r ON r.vid = n.vid;

+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref          | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
|  1 | SIMPLE      | u     | ALL    | PRIMARY       | NULL    | NULL    | NULL         |  181 |             | 
|  1 | SIMPLE      | n     | ref    | vid,uid       | uid     | 4       | xyz.u.uid |    9 | Using where | 
|  1 | SIMPLE      | r     | eq_ref | PRIMARY       | PRIMARY | 4       | xyz.n.vid |    1 |             | 
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+

Toute idée de ce que pourrait se passer, et comment je pourrais forcer MYSQL à utiliser Index sur cette requête?

Était-ce utile?

La solution

Les tableaux ne sont pas nécessairement jointes dans l'ordre qu'ils sont spécifiés dans la clause FROM. Dans ce cas, il semble que MySQL a décidé qu'en l'absence d'une clause de WHERE dans la requête, il est probablement le plus rapide pour scanner la table des utilisateurs d'abord, puis les rejoindre que d'autres tables.

La première chose que je ferais serait de courir ANALYZE TABLE sur les trois tables impliquées dans la requête. Cette mise à jour des statistiques de table et stockées distributions clés, et permet à la rejoindre optimiseur de prendre de meilleures décisions. Exécutez l'instruction EXPLAIN par la suite et voir si elle a changé.

Si elle n'a pas changé, vous pourriez avoir besoin de recourir à l'aide du mot-clé STRAIGHT_JOIN. Cela force la jointure optimiseur pour joindre les tables dans l'ordre exact spécifié dans la requête. Pour aider à déterminer si vous devez le faire, vous êtes censé prendre le produit de toutes les valeurs de rows d'un résultat EXPLAIN, et le comparer au nombre réel de lignes renvoyées par la requête. Donc dans ce cas, comparer 1629 (181x9x1) au nombre réel de lignes. Si elles sont significativement différentes, un STRAIGHT_JOIN pourrait être appelé à (utilisé comme mot-clé pour SELECT, par exemple. SELECT STRAIGHT_JOIN n.nid ... etc).

En aparté, il y a un moyen de dire MySQL d'utiliser un index spécifique , mais je ne pense pas que cela fonctionnerait pour votre table utilisateur dans cette requête car il est en ce moment, car il n'y a pas de clause de WHERE. Si vous vous retrouvez à l'aide STRAIGHT_JOIN, vous pourriez avoir besoin, mais dans ce cas, MySQL serait probablement revenir sur la clé primaire si la table utilisateur n'a pas été la première table dans la jointure.

Vous devriez jeter un oeil à la syntaxe EXPLIQUER page pour plus de détails plus utiles à ce sujet également.

Cette requête ne semble pas comme il devrait être que lent pour ce qu'elle est. Sans une clause where, vous pouvez vous attendre un scan table complète quelque part, et MySQL a gardé jusqu'à environ 1700 lignes au total examinées. Il semble que ce serait un problème que si elle était une requête forte utilisation, dans ce cas, vous voudrez peut-être examiner l'architecture sous-jacente (sans clause de WHERE) consiste à exécuter une requête qui affectera tous les utilisateurs du système, et ne fera plus lourd que d'autres utilisateurs sont ajoutés.

Autres conseils

Depuis MySQL ne peut utiliser un index par table par requête que vous pouvez parfois obtenir un indice de gamme « libre » par balayage juste jeter dans cet état apparemment inutile.

WHERE u.uid > 0

Essayez d'ajouter cette clause, probablement le scan de table ALL va changer à une « gamme », ce qui est mieux qu'un scan de table.

Cela pourrait-il aider?

noeud de table, créer un index sur (uid, vid) ALTER TABLE 'xyz_node' ADD INDEX user_ver ( 'uid,' vid ») (Notez la 2ème ligne de la sortie expliquer .. sous la rubrique clés possibles .. vous voyez vid, uid)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top