0

J'ai un problème avec une requête mySQL, car il prend trop de temps (environ 12 secondes) la table ont environ 70 000 dossiersma requête mySQL prend trop de temps (environ 12 secondes) - toute suggestion

ici est ma requête:

SELECT DATE(`orders`.`date`) AS `dater`, 
     COUNT(*) AS `amount`, 
     (SELECT SUM(`amount`) FROM `payment` 
       WHERE DATE(`dater`)=DATE(`payment`.`posted_date`) 
     ) AS `charge` 
    FROM `orders` 
    GROUP BY `dater` 
    ORDER BY `dater` DESC 
    LIMIT 0,10 

Comme vous pouvez le voir il y a 2 tables 1. tableau: commandes ce sont les tables de commandes ici, nous avons une colonne principale: la date (nous avons besoin ici pour compter les commandes par jour)

échantillon:

-------------------- 
date  | id 
-------------------- 
01-01-2017 | 1 
-------------------- 
01-01-2017 | 2 
-------------------- 
01-02-2017 | 3 
-------------------- 
  1. table: paiement: il est la table des paiements nous avons ici 2 colonnes principales: posted_date, le montant (nous avons besoin ici pour obtenir la somme du champ montant pour la toute jour)
échantillon

:

-------------------- 
posted_date | amount 
-------------------- 
01-01-2017 | 100 
-------------------- 
01-01-2017 | 50 
-------------------- 
01-02-2017 | 200 
-------------------- 

donc à la fin les résultats devraient être [date, le montant, la charge]

sûr en moins de temps, car il est impossible d'aller avec cette 12 secondes: D

Je vois que le problème est sur cette interne SELECT:

(SELECT SUM(`amount`) FROM `payment` 
    WHERE DATE(`dater`)=DATE(`payment`.`posted_date`) 
) AS `charge` 

toute suggestion de comment puis-je éviter de faire SELECT l'intérieur la requête SELECT?

+1

Peut-être envisager d'indexer vos tables de données –

+3

Cela 'COUNT (*)' est également un problème. Il doit passer par toute votre table et s'il n'est pas correctement indexé, il est encore pire. –

+1

Pouvons-nous voir votre schéma? –

Répondre

1

Vous avez une sous-requête corrélée. Le planificateur de requêtes de MySQL gère ceux-ci d'une manière naïve, pour le dire poliment.

Refactorisez votre requête pour utiliser une jointure à la place. Votre sous-requête corrélée ressemblerait à ceci comme une requête joinable.

  SELECT SUM(amount) charge, 
        DATE(posted_date) posted_date 
      FROM payment 
      GROUP BY DATE(posted_date) 

Ceci obtient une ligne par jour à partir de la table de paiement.

Ensuite, vous devez obtenir un résultat similaire de votre table de commandes.

  SELECT DATE(date) AS dater, 
       COUNT(*) AS amount 
      FROM orders 
      GROUP BY DATE(date) 

Alors, joignez-vous ces deux ensemble

SELECT a.dater, a.amount, b.charge 
    FROM (
     SELECT DATE(date) AS dater, 
       COUNT(*) AS amount 
      FROM orders 
      GROUP BY DATE(date) 
     ) a 
    LEFT JOIN (
      SELECT SUM(amount) charge, 
        DATE(posted_date) posted_date 
      FROM payment 
      GROUP BY DATE(posted_date) 
     ) b ON a.dater = b.posted_date 
ORDER BY a.dater DESC 
LIMIT 0,10 

Il est nécessaire de joindre deux sous-requêtes ici, parce que vous avez besoin de deux agrégats par date pour la jonction au travail.

+0

Cela peut être accéléré en ajoutant 'ORDER BY ... LIMIT 10' dans chaque sous-requête. Le montant de l'accélération dépend quadratiquement du nombre de dates. –