此脚本使用php和mysql计算一分钟滚动平均值,以减少异常值对我的数据的影响(一分钟= 6 10秒行)。它正确计算所有内容,但效率不足以一次完成超过150行。我想一次做尽可能多的行,可能在5-10,000之间,因为我的表超过150,000,而且我每天输入大约8,000行。
有没有人对如何让这个脚本更高效地运行有任何建议?
谢谢!
<?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'");
}
答案 0 :(得分:1)
对于初学者,可以通过添加COUNT()
聚合来清除此处的初始“计数”块:
$resultA = mysql_query("SELECT * FROM table");
$num_rows = mysql_num_rows($result);
echo "There are $num_rows rows.</br>";
更改为:
$resultA = mysql_query("SELECT COUNT(*) FROM table");
$row = mysql_fetch_array($result);
$num_rows = $row[0];
echo "There are $num_rows rows.</br>";
这应该可以自己加快速度。如果没有它,您将从表中选择所有数据 - 这个查询只会越多,放入表中的速度越慢。
对于您正在计算的平均值,是否需要在MySQL查询中无法直接完成的逻辑?例如:
UPDATE table SET PortMinuteAveRPM=(SELECT AVG(PortRPMSignal) FROM table WHERE Timestamp BETWEEN '$startTime' AND '$endTime') WHERE TimeStamp='$endTime'
如果这看似合理,这可以帮助您避免循环结果。
答案 1 :(得分:1)
听起来你正试图计算一个自回归移动平均线(ARMA),但是你对数据的解释以及如何捕获它有很多问题。
如果你有一套完整的数据(虽然你的问题意味着你没有),那么找出时间间隔包含所需数量的记录并直接从数据库中获取,例如
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
如果你想减少数据点,那么试试像......
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
虽然如果你没有完整的数据集但是只有少量的抖动是一个更好的解决方案,那就是使用自动增量id的模数从'a'中挑出更少的行
答案 2 :(得分:0)
这只是一个开始,但你可以把这个位
//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>";
因为以下行
$resultB = mysql_query("SELECT PortRPMSignal FROM table");
...将为您提供一个可以使用mysql_num_rows的结果集。
在查询中使用*
会增加数据库的负载。
在你的for循环中你有了这个
$temp = mysql_query("SELECT Timestamp FROM table");
if(!$temp){
die('Could not query:' . mysql_error());
}
这意味着每次循环时都会运行此查询,而您甚至不使用结果。
我不知道mysqli是否会给你更好的表现,但你应该使用它。