You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP调用CheckAQI函数渲染HighChart图表时加载速度过慢问题咨询

性能问题核心原因

单次CheckAQI执行会触发2次数据库查询,当前业务需要查询3个站点、过去14天的AQI数据,循环累计触发84次数据库查询,是加载慢的核心诱因。另外代码存在低级错误、查询无索引、冗余逻辑也进一步放大了性能损耗。


具体优化方案

1. 先修复现有代码明显错误

  • 两个PHP函数的参数定义为$connection,实际内部调用的连接变量是$con,参数不匹配
  • pollute_data函数的参数列表末尾缺右括号
  • Township系列的AQI计算结果变量是$GraphTownshipAQI,判断是否为空用的是$GraphMobileAQI,变量名错误导致数据异常

2. 数据库层优化

  • 给test_uploads表加联合索引:ALTER TABLE test_uploads ADD INDEX idx_stat_date (station_id, dateandtime, O3),走覆盖索引查询日均数值无需回表,单次查询耗时可从几十毫秒降到1毫秒以内
  • AQI分级规则是固定配置,无需每次计算都查库,提前一次性加载到内存即可
// 全局提前加载所有AQI分级规则,只查1次库
$aqi_rules = [];
$sql = "SELECT * FROM aqiindex";
$res = mysqli_query($con, $sql);
while($row = mysqli_fetch_assoc($res)) {
    $aqi_rules[] = $row;
}

// 改造pollute_data直接从内存匹配规则,完全省去库查询
function pollute_data($pollutant, $pollutant_value, $aqi_rules) {
    $pollutant_lower = strtolower($pollutant);
    $col1 = $pollutant_lower. '_lower';
    $col2 = $pollutant_lower. '_upper';
    foreach($aqi_rules as $rule) {
        if($pollutant_value >= $rule[$col1] && $pollutant_value <= $rule[$col2]) {
            return [$rule[$col1], $rule[$col2], $rule['aqi_lower'], $rule['aqi_upper']];
        }
    }
    return [0,0,0,0];
}

3. 批量查询业务数据,替代循环单条查询

原来42次单站点单日期的查询,改成1次SQL拉取所有需要的原始数据:

// 计算查询的时间范围
$end_date = $date;
$start_date = date("Y-m-d", strtotime("-14 day", strtotime($end_date)));
// 一次性查询3个站点14天的日均O3数据
$sql = "
SELECT 
    station_id,
    DATE(dateandtime) as stat_date,
    SUM(O3)/COUNT(O3) as o3_polluant
FROM test_uploads 
WHERE 
    dateandtime >= '$start_date 00:00:00' 
    AND dateandtime <= '$end_date 23:59:59' 
    AND station_id IN (1,2,3)
GROUP BY station_id, DATE(dateandtime)
";
$res = mysqli_query($con, $sql);
// 整理成 站点ID->日期->数值 的数组方便后续取值
$station_data = [];
while($row = mysqli_fetch_assoc($res)) {
    $station_data[$row['station_id']][$row['stat_date']] = $row['o3_polluant'];
}

4. 后端统一组装图表数据,前端直接渲染

避免在JS代码里嵌套多层PHP循环,后端提前组装成HighChart需要的JSON格式,既减少冗余逻辑也避免JS语法错误:

// 组装横轴日期和三个站点的序列数据
$categories = [];
$series = [
    ['name' => 'Township AQMS', 'data' => []],
    ['name' => 'Townhall AQMS', 'data' => []],
    ['name' => 'Mobile AQMS', 'data' => []],
];

$my_date = $date;
for($i=1;$i<15;$i++) {
    $time = strtotime("-1 day",strtotime($my_date));
    $my_date = date('Y-m-d', $time);
    $categories[] = date("d,m,Y", $time);
    // 循环三个站点计算AQI
    foreach([1,2,3] as $idx => $station_id) {
        $o3_val = $station_data[$station_id][$my_date] ?? 0;
        $aqidata = pollute_data('O3', $o3_val, $aqi_rules);
        // AQI计算逻辑和原代码一致
        $pl_lower = $aqidata[0];
        $pl_upper = $aqidata[1];
        $aqi_lower = $aqidata[2];
        $aqi_upper = $aqidata[3];
        $Idiff = $aqi_upper - $aqi_lower;
        $Bpdiff = $pl_upper - $pl_lower;
        $aqi = $Bpdiff > 0 ? (($Idiff * ($o3_val - $pl_lower)) / $Bpdiff) + $aqi_lower : 0;
        $aqi = floor($aqi * 100) / 100;
        $series[$idx]['data'][] = is_nan($aqi) ? 0 : $aqi;
    }
}

// 转成JSON供前端直接使用
$categories_json = json_encode($categories);
$series_json = json_encode($series);

前端代码简化为:

<script src="highchart/highcharts.src.js"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
    Highcharts.chart('container', {
        chart: { type: 'column' },
        title: { text: 'AQI Historic Data' },
        xAxis: { categories: <?php echo $categories_json; ?> },
        yAxis: { title: { text: 'AQI Range' } },
        series: <?php echo $series_json; ?>
    });
});
</script>

5. 后续扩展6种污染物的兼容方案

批量查询的SQL里新增其他污染物的均值计算字段,AQI计算时遍历6种污染物分别计算、取最大值作为当日AQI即可,无需修改核心逻辑结构。

6. 可选进阶优化

如果页面访问量较高,可以把计算好的14天AQI数据存入文件缓存或者Redis,缓存有效期设为1~24小时(根据数据更新频率调整),无需每次请求都重新计算,页面加载耗时可降到100毫秒以内。


内容的提问来源于stack exchange,提问作者Hafiz Muhammad Ejaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 18:45:04