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

PHP memory_get_usage返回负值求助:大表查询内存测量异常

问题原因:内存溢出触发整数溢出

你的q1查询返回1100万+行数据,fetchAll()会把所有结果一次性加载到PHP内存中。如果你的PHP是32位版本,memory_get_usage()返回的是有符号32位整数,最大值约为2147MB(2^31-1)。当内存占用超过这个阈值时,整数会溢出,数值直接翻转成负数——这就是$m2出现负值的核心原因。

而q2因为做了group by cid,结果集行数大幅减少(最多为1100万行,最少约360万行),内存占用未突破32位整数上限,所以能正常显示数值。


正确测量内存的方案

  1. 切换到64位PHP环境
    64位PHP的整数类型支持极大的数值范围(最大值约9e18),可以准确记录超过2GB的内存占用,从根源上避免整数溢出导致的负值问题。

  2. 避免一次性加载全量结果
    放弃fetchAll()一次性加载所有数据的做法,改用逐行或分批获取的方式处理结果,既能大幅降低内存占用,也能更精准地测量单批数据的内存消耗:

    function test($query){
        $m1 = memory_get_usage();
        $q = DB->query($query);
        $rowCount = 0;
        while ($row = $q->fetch()) {
            $rowCount++;
            // 在这里处理单条数据逻辑
        }
        $m2 = memory_get_usage();
        return [$m2, $m1, $rowCount];
    }
    
  3. 使用峰值内存测量函数
    改用memory_get_peak_usage()替代memory_get_usage(),它返回脚本执行过程中使用的内存峰值,能更准确反映查询和结果处理过程中实际占用的最大内存,避免因测量时机偏差导致的结果不准:

    function test($query){
        $m1 = memory_get_peak_usage();
        $q = DB->query($query);
        $r = $q->fetchAll();
        $m2 = memory_get_peak_usage();
        return [$m2, $m1];
    }
    
  4. 谨慎调整PHP内存限制
    如果必须一次性加载全量数据,可以临时调大php.ini中的memory_limit(例如设置为4G),但这只是应急方案——大结果集一次性加载始终是低效且易引发内存溢出的做法,不建议长期使用。

内容的提问来源于stack exchange,提问作者PM_KLS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 10:12:13