Rolling Average Efficiency, php mysql

Ce script utilise php et mysql pour calculer une moyenne mobile d'une minute pour réduire l'impact des valeurs aberrantes sur mes données (une minute = 6 lignes de 10 secondes). Il calcule tout correctement, mais n'est pas assez efficace pour faire plus de 150 lignes à la fois. Je voudrais faire autant de lignes que possible à la fois, peut-être entre 5 à 10 000, car ma table est supérieure à 150 000 et j'adore environ 8 000 lignes par jour.

Est-ce que quelqu'un a des suggestions quant à la façon dont je peux faire fonctionner ce script de manière plus efficace?

Merci!

<?php //connect to database mysql_connect("localhost","user","password");//database connection mysql_select_db("database"); $result = mysql_query("SELECT Timestamp FROM table"); if (!$result) { die('Could not query:' . mysql_error()); } //get number of rows in table $resultA = mysql_query("SELECT * FROM table"); $num_rows = mysql_num_rows($result); echo "There are $num_rows rows.</br>"; //select column to be averaged $resultB = mysql_query("SELECT PortRPMSignal FROM table"); if (!$resultB) { die('Could not query:' . mysql_error()); } //set start equal to the first row you want to calculate the averages from, likely the first null row $start = 5; //calculate 1 minute average, the average is correct for($i = $start; $i<$num_rows; $i++){ $output = mysql_result($result,$i); $test = mysql_result($resultB,$i)+mysql_result($resultB,$i-1)+mysql_result($resultB,$i-2)+mysql_result($resultB,$i-3)+mysql_result($resultB,$i-4)+mysql_result($resultB,$i-5); $test2 = $test/6; $round = round($test2,4); $temp = mysql_query("SELECT Timestamp FROM table"); if(!$temp){ die('Could not query:' . mysql_error()); } //gets timestamp at row $i, and inserts new average value into that row in RPMAve column $time = mysql_result($result,$i); mysql_query("UPDATE table SET PortMinuteAveRPM = $round WHERE Timestamp = '$time'"); } 

Pour commencer, le bloc "count" initial peut être nettoyé en ajoutant l'agrégat COUNT() :

 $resultA = mysql_query("SELECT * FROM table"); $num_rows = mysql_num_rows($result); echo "There are $num_rows rows.</br>"; 

Passer à:

 $resultA = mysql_query("SELECT COUNT(*) FROM table"); $row = mysql_fetch_array($result); $num_rows = $row[0]; echo "There are $num_rows rows.</br>"; 

Cela devrait accélérer considérablement les choses. Sans cela, vous select toutes datatables de la table – une requête qui ne fera que ralentir plus vous mettez dans la table.

Pour les moyennes que vous utilisez, une logique est-elle nécessaire qui ne peut pas être effectuée directement dans une requête MySQL? Quelque chose comme:

 UPDATE table SET PortMinuteAveRPM=(SELECT AVG(PortRPMSignal) FROM table WHERE Timestamp BETWEEN '$startTime' AND '$endTime') WHERE TimeStamp='$endTime' 

Cela peut vous empêcher de boucler les résultats, si cela est plausible.

Il semble que vous essayez de calculer une moyenne mobile autorégressive (ARMA), mais il existe de nombreux problèmes avec votre interprétation de vos données et la façon dont vous la capturez.

Si vous avez un set complet de données (bien que votre question implique que vous ne le faites pas), profitez de l'intervalle de time contenant la quantité requirejse d'loggings et obtenez-le directement à partir de la database, par exemple

 SELECT a.timestamp as base, AVG(b.PortRPMSignal) FROM table a, table b WHERE b.timestamp BETWEEN a.timestamp AND a.timestamp+INTERVAL 6 HOUR GROUP BY a.timestamp 

Si vous souhaitez affiner les points de données, essayez quelque chose comme ….

 SELECT a.timestamp as base, AVG(b.PortRPMSignal) FROM table a, table b WHERE b.timestamp BETWEEN a.timestamp AND a.timestamp+INTERVAL 6 HOUR AND DATE_FORMAT(a.timestamp, '%i%s')='0000' GROUP BY a.timestamp 

Bien qu'une meilleure solution si vous n'avez pas un set de données complet, mais il n'y a qu'une petite quantité de gigue serait d'utiliser le module d'un ID d'auto-incrémentation pour choisir less de lignes de 'a'

Ce n'est qu'un début, mais vous pouvez lancer ce bit

 //get number of rows in table $resultA = mysql_query("SELECT * FROM table"); $num_rows = mysql_num_rows($result); echo "There are $num_rows rows.</br>"; 

Parce que la ligne suivante

 $resultB = mysql_query("SELECT PortRPMSignal FROM table"); 

… vous donnera un set de résultats sur lequel vous pouvez utiliser mysql_num_rows.

L'utilisation du * dans une requête augmente la charge sur la database.

Dans votre boucle, vous avez alors cette

 $temp = mysql_query("SELECT Timestamp FROM table"); if(!$temp){ die('Could not query:' . mysql_error()); } 

ce qui signifie que cette requête s'exécute chaque fois que vous vous bouclez et que vous n'utilisez même pas les résultats.

Je ne sais pas si mysqli vous donnera de meilleures performances, mais vous devriez l'utiliser.