0
votes

Pouvez-vous optimiser ce code de requête PHP boucle?

J'ai des problèmes de performance avec mon site Web Laravel. J'ai pu découvrir que la raison de cela fait partie de mon code. Je fais des questions dans une boucle qui ne devrait pas être faite comme je viens de découvrir. Je ne sais pas comment je peux optimiser ce code dans le meilleur moyen (sans changer la base de données car ce n'est pas aussi facile à ce stade du projet).

Je pensais à améliorer la partie avec le foreach < / code> $ transactioninfos au moins kenta comme celui-ci, mais je ne suis pas sûr de la syntaxe Laravel avec laquelle maintenant: xxx

Le code actuel : xxx

Je m'attends à obtenir un tableau avec une liste de tous les outils avec des tableaux de chaque utilisateur de 30 jours, par exemple:

  • [13] [0] = 20
  • [13] [1] = 6
  • [13] [2] = 24
  • ..
  • [13] [29] = 10

  • ..

  • [18] [0] = 50

  • [18] [1] = 11
  • [18] [2] = 55
  • ..
  • [18] [29] = 6

    https://i.imgur.com/vdyz9un.png (L'exemple d'image montre 0 utilisateur en raison d'un dB vide local, mais c'est comme ça qu'il devrait ressembler).


2 commentaires

Montrez-nous le SQL généré afin que nous puissions aborder le problème de ce côté.


J'ai eu un problème similaire avec la création de statistiques. Je l'ai résolu avec la mise en cache en combinaison avec une commande et une planification générées. Vous savez que les données passées ne changeront pas. Si la journée actuelle change, adaptez les données en cache sur cet endroit particulier dans la matrice multidimimé et refaire la cache. Cela peut être fait en créant un événement en combinaison avec les files d'attente. Exécutez le calendrier 30D à minuit. Si le cache (d gray) est trop gros, vous pouvez l'enregistrer en tant que fichier.


3 Réponses :


1
votes

Il y a quelques éléments que vous pouvez faire pour aider à accélérer cela pour améliorer les performances et réduire vos hits à la base de données / appel à la fonction.

Premièrement, vous pouvez tirer tout votre ToolTransactionIfo code> à la fois, avant de boucler. Cela vous aidera à faire seulement une db tirer. Donc, au-dessus de votre boucle: p> xxx pré>

Cela vous donne toutes les infos dont vous avez besoin. Ensuite, à l'intérieur de votre boucle, vous pouvez faire la même requête, mais le faire sur la collection déjà en mémoire (c.-à-d. Ne revenez pas à la base de données). P>

$date = $now->subDays($count)->format('Y-m-d');


7 commentaires

Merci pour vos suggestions. Malheureusement, j'obtiens l'erreur suivante à ce stade "où (" Tool_id ", $ Tool-> ID)" Méthode non statique Illuminate \ Support \ Collection :: Où () ne doit pas être appelé statique.


Ooops - désolé - faites-la non statique. $ transactioninfostotal-> où ('tool_id', $ outil-> id) . Je vais éditer ma réponse à la solution.


Cela n'a pas besoin de -> get (); à la transaction $Infos. Puis $ maintenant = carbone (maintenant); Cela ne fonctionne pas, car il sera substitué maintenant en faisant $ maintenant-> des sous-dimensions ($ comptez), donc je sous le sous-titré tout le temps au lieu de la reprendre à nouveau du carbone pour le réinitialiser.


Malheureusement, cela le rend même plus lent puisqu'il doit charger 150 000 données dans une requête. Avec l'autre, il fait comme 50 DB requêtes, mais chacun ne choisit que 30 données. sa 30 secondes vs 5 sec.


Oui, je vois ce que tu veux dire. Avec ce volume de données, vous devrez accorder la requête pour prendre une tranche. Je vous recommande toujours de ne pas le faire dans la boucle, mais faites une pré-requête avec un certain niveau de filtrage à venir. 30 secondes est folle longtemps pour une requête - même ce volume. Avec la chose à la fois $, utilisez une deuxième variable TEMP - c'est toujours la bonne méthode, plutôt que d'appeler à chaque fois.


Je l'ai essayé avec une deuxième variable Temp, cela change toujours le principal.


@Dappfuture mec, vérifiez ma réponse, il vous donnera tout le résultat directement à partir de DB avec une seule requête. Aucune donnée supplémentaire transférée entre PHP et DB.



1
votes

Vous pouvez réduire l'algorithme entier à une seule requête SQL, quelque chose comme ceci (il le gère, il a besoin de citations au moins ...), vous aurez juste besoin d'une seule passe dans le résultat pour construire la matrice multidimensionnelle cible. .

SELECT tool_id, 30 - datediff(now(), date) as "offset", sum(users)
FROM transaction_info
WHERE date >= (date(now()) - interval 30 days) AND date < date(now())
GROUP BY tool_id, 30 - datediff(now(), date)


4 commentaires

Va voir comment faire cette requête dans Laravel et donner des commentaires s'il a fonctionné.


La requête SQL fonctionne et semble être la bonne manière, j'écrirai le code de Laravel quand je l'ai eu.


OK, BTW, la partie avec "30 - Daturadiff (maintenant ((), date)", c'est-à-dire juste pour correspondre parfaitement à vos décalages, mais je pense que cela pourrait fonctionner mieux si vous avez simplement "Sélectionner la date de date par date", et compter le décalage (jours avant aujourd'hui) sur le côté PHP. Cela pourrait donc être meilleur pour la performance et, après tout, il peut même être plus facile d'adapter les wrappers Laravel ...


Oui, je pensais la même chose que j'utilisais juste à la date. Vérifiez simplement comment faire le tableau si nécessaire après la requête, le postera bientôt pour examen.



0
votes

La requête de Highpic était la voie à suivre. Il a amélioré la charge totale de la page de 3,8 à 2,5 secondes (page de données lourdes mais encore quelques améliorations todynamique), mais c'était l'une des 2 fonctions les plus lourdes que je pourrais améliorer. Merci à toitoire et à toutes les autres suggestions.

Voici ma solution: xxx


1 commentaires

BTW, vous voudrez peut-être ajouter un index composé sur (Tool_ID, date), voir si elle fait une différence. Eh bien, je suppose que Tool_id a déjà un index. Dans ce cas incorporer la colonne Date de cet indice, au lieu de créer un autre. Essayez également un index seul sur la colonne Date. Voyez ce qui serait mieux. La nécessité d'index n'est pas statique, cela dépend de la taille de la table et de la capacité des requêtes d'utiliser l'index. Donc, il a besoin d'ajuster avec le temps ...