Question

J'ai des requêtes qui utilisent des vues, et celles-ci sont beaucoup plus lentes que je ne le pensais, étant donné que toutes les tables pertinentes sont indexées (et pas si grandes de toute façon).

J'espère pouvoir expliquer ceci:

Ma requête principale ressemble à ceci (grossièrement simplifiée)

select [stuff] from orders as ord 
left join calc_order_status as ors on (ors.order_id = ord.id)

calc_order_status est une vue, définie ainsi:

create view calc_order_status as
select ord.id AS order_id,
(sum(itm.items * itm.item_price) + ord.delivery_cost) AS total_total
from orders ord 
left join order_items itm on itm.order_id = ord.id
group by ord.id

Les commandes (ord) contiennent des commandes, order_items contient les articles individuels associés à chaque commande et leurs prix.

Toutes les tables sont correctement indexées, MAIS la chose tourne lentement et quand je fais un EXPLAIN je reçois

  # id  select_type  table  type  possible_keys  key  key_len  ref  rows  Extra  
  1 1 PRIMARY ord ALL customer_id NULL NULL NULL 1002 Using temporary; Using filesort 
  2 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 1002   
  3 1 PRIMARY cus eq_ref PRIMARY PRIMARY 4 db135147_2.ord.customer_id 1 Using where 
  4 2 DERIVED ord ALL NULL NULL NULL NULL 1002 Using temporary; Using filesort 
  5 2 DERIVED itm ref order_id order_id 4 db135147_2.ord.id 2   

Mon hypothèse est: "dérivé2" fait référence à la vue. Les éléments individuels (itm) semblent bien fonctionner, indexés par ordre _ id. Le problème semble être la ligne 4, ce qui indique que le système n'utilise pas de clé pour la table orders (ord). Mais dans la requête MAIN, l'ID de commande est déjà défini:    gauche rejoindre calc_order_status en tant que ous sur (ors.order _ id = ord.id) et ord.id (dans la requête principale et dans la vue) font référence à la clé primaire.

J’ai lu quelque part que MySQL n’optimise pas très bien les vues et n’utilise peut-être pas les clés dans certaines conditions, même si elles sont disponibles. Cela semble être l'un de ces cas.

J'apprécierais vos suggestions. Existe-t-il un moyen de forcer MySQL à se rendre compte que "tout est plus simple que vous ne le pensez, utilisez simplement la clé primaire et tout ira bien" Ou les points de vue sont-ils la mauvaise façon de procéder?

Était-ce utile?

La solution

S'il est possible de supprimer ces jointures, supprimez-les. Les remplacer par des sous-requêtes accélérera beaucoup.

vous pouvez également essayer d'exécuter quelque chose comme ceci pour voir s'il y a une différence de vitesse.

select [stuff] from orders as ord 
left join (
  create view calc_order_status as
  select ord.id AS order_id,
  (sum(itm.items * itm.item_price) + ord.delivery_cost) AS total_total
  from orders ord 
  left join order_items itm on itm.order_id = ord.id
  group by ord.id
) as ors on (ors.order_id = ord.id) 

Autres conseils

Un index est utile pour rechercher quelques lignes dans une grande table, mais lorsque vous interrogez chaque ligne, un index ralentit les choses. Donc ici, MySQL s'attend probablement à utiliser toute la table [order], il est donc préférable de ne pas utiliser d'index.

Vous pouvez essayer de gagner du temps en forcer MySQL pour utiliser un index:

from orders as ord force index for join (yourindex)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top