2010-09-28 5 views
0

Cette requête apparaît dans mes journaux de requêtes lentes:quel (s) index (s) doit-on ajouter pour que cette requête fonctionne correctement?

SELECT 
    COUNT(*)     AS ordersCount, 
    SUM(ItemsPrice + COALESCE(extrasPrice, 0.0)) AS totalValue, 
    SUM(ItemsPrice)   AS totalValue, 
    SUM(std_delivery_charge) AS totalStdDeliveryCharge, 
    SUM(extra_delivery_charge) AS totalExtraDeliveryCharge, 
    this_.type    AS y5_, 
    this_.transmissionMethod AS y6_, 
    this_.extra_delivery  AS y7_ 
FROM orders this_ 
WHERE this_.deliveryDate BETWEEN '2010-01-01 00:00:00' AND '2010-09-01 00:00:00' 
    AND this_.status IN(1, 3, 2, 10, 4, 5, 11) 
    AND this_.senderShop_id = 10017 
GROUP BY this_.type, this_.transmissionMethod, this_.extra_delivery 
ORDER BY this_.deliveryDate DESC; 

La table est InnoDB et a environ 880K lignes et prend entre 9-12 secondes pour exécuter. J'ai essayé d'ajouter l'index suivant ALTER TABLE orders ADD INDEX _deliverydate_senderShopId_status (deliveryDate , senderShop_id , status, type, transmissionMethod, extra_delivery); sans gains pratiques. Toute aide et/ou suggestion est la bienvenue

Voici le plan d'exécution de la requête en ce moment:

 
id  select_type table type possible_keys key     key_len ref rows filtered Extra 
1  SIMPLE  this_ ref      FKC3DF62E57562BA6F 8   const 139894 100.00 Using where; Using temporary; Using filesort 

Je pris la valeur possible_keys sur le texte parce que je pense qu'il inclut tous les index de la table. La clé utilisée (FKC3DF62E57562BA6F) ressemble

 
Keyname    Type Unique Packed Field   Cardinality Collation Null Comment 
FKC3DF62E57562BA6F BTREE No  No  senderShop_id 4671  A 
+0

Quel est le type de colonne de deliveryDate? – Thilo

+0

L'indexation doit être effectuée conjointement avec l'analyse des plans de requête pour voir comment ils sont réellement utilisés. Il n'est pas toujours évident de savoir comment la base de données utilisera l'index en fonction de l'optimisation effectuée par la base de données. Postez votre plan de requête avec cet index, puis nous serons dans une meilleure position pour aider – InSane

+0

@Thilo - deliveryDate est datetime –

Répondre

1

Je vais vous dire une chose que vous pouvez regarder pour augmenter la vitesse.

Vous ne disposez généralement que des valeurs NULL dans les données pour les lignes inconnues ou non applicables. Il me semble que, puisque vous traitez NULL comme 0 de toute façon, vous devriez penser à se débarrasser d'eux et s'assurer que toutes les valeurs extrasPrice sont 0 où ils étaient précédemment NULL afin que vous puissiez vous débarrasser de la pénalité de temps de la coalesce.

En fait, vous pouvez aller un peu plus loin et d'introduire une autre colonne appelé totalPrice que vous définissez avec un déclencheur d'insertion/mise à jour à la valeur réelle ou ItemsPrice + extrasPrice (ItemsPrice + COALESCE(extrasPrice,0.0) si vous avez encore besoin de extrasPrice valeur NULL).

Ensuite, vous pouvez simplement utiliser:

SELECT 
    COUNT(*)   AS ordersCount, 
    SUM(totalPrice) AS totalValue, 
    SUM(ItemsPrice) AS totalValue2, 
    : 

(Je ne suis pas sûr que vous devriez avoir deux colonnes de sortie avec le même nom ou si cela était une faute de frappe, qui va être, au pire, un erreur, au mieux, source de confusion). Cela déplace le coût du calcul pour insérer/mettre à jour le temps plutôt que de sélectionner le temps et amortit ce coût sur toutes les sélections - la plupart des tables de base de données sont lues beaucoup plus souvent que écrites. La cohérence des données est maintenue grâce au déclencheur et les performances devraient être meilleures, au détriment de certaines exigences de stockage. Mais, puisque la grande majorité des questions de base de données sont "Comment puis-je obtenir plus de vitesse?" plutôt que "Comment puis-je utiliser moins de disque?", c'est souvent une bonne idée.

Une autre suggestion consiste à fournir un index non composite sur la colonne qui réduit le résultat défini le plus rapidement (cardinalité élevée). En d'autres termes, si vous ne stockez que deux semaines de données (14 dates différentes) dans votre tableau mais 400 boutiques différentes, vous devriez avoir un index sur senderShop_id et vous assurer que vos statistiques sont à jour. Cela devrait amener le moteur d'exécution du SGBD à réduire le jeu de résultats à l'aide de cette touche afin que les opérations suivantes soient plus rapides.

Un indice composite sur deliveryDate,senderShop_id,... ne sera pas en mesure d'utiliser senderShop_id pour rogner les résultats parce que la commande clé sera senderShop_idau seindeliveryDate.

Questions connexes