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

Microsoft Graph API PHP SDK:5万用户集合高效分页方式咨询

高效处理Microsoft Graph API大规模用户数据拉取:直接利用@odata.nextLink优化内存与性能

我之前处理过几万条用户数据的同步场景,太懂你用array_merge堆出大数组的痛苦了——5万条数据全塞内存里,不仅慢,还容易爆内存。直接用@odata.nextLink逐页处理才是应对大规模数据的正确姿势,下面给你详细讲怎么实现:

为什么原方法效率低?

原来的while (!$docGrabber->isEnd()) + array_merge模式,会把每一页的用户数据都合并到同一个大数组里。5万条数据的话,这个数组会持续占用内存,而且array_merge每次都要复制现有数组,随着数据量增大,性能下降会越来越明显。

直接用@odata.nextLink的优化思路

核心是放弃一次性存储所有数据,改为逐页获取、逐页处理,处理完当前页就释放内存,始终保持内存占用在单页数据的量级。Graph API返回的@odata.nextLink就是用来直接请求下一页的,我们可以手动利用它来循环拉取。

具体代码实现

use Microsoft\Graph\Graph;

// 假设你已经初始化好$graphClient(包含认证配置)
$graphClient = new Graph();
// ... 省略client认证逻辑 ...

// 第一步:发起第一页请求,设置每页最大数量(Graph API支持最多999条/页)
$initialRequest = $graphClient->createCollectionRequest('GET', '/users')
    ->top(999); // 调大每页数量,减少请求次数

$response = $initialRequest->execute();
$pageData = $response->getBody();

// 处理第一页数据
processUserPage($pageData['value']);

// 第二步:循环利用@odata.nextLink拉取下一页
while (isset($pageData['@odata.nextLink'])) {
    // 直接用nextLink创建新请求
    $nextRequest = $graphClient->createCollectionRequest('GET', $pageData['@odata.nextLink']);
    $nextResponse = $nextRequest->execute();
    $pageData = $nextResponse->getBody();
    
    // 处理当前页数据
    processUserPage($pageData['value']);
    
    // 可选:手动释放当前页的响应对象,进一步降低内存占用
    unset($nextResponse);
}

/**
 * 自定义的页面数据处理函数
 * 这里可以根据你的业务需求做操作:写入数据库、导出CSV、批量处理等
 */
function processUserPage(array $users) {
    foreach ($users as $user) {
        // 示例:打印用户ID(替换成你的业务逻辑)
        echo "处理用户:" . $user['id'] . "\n";
        
        // 比如写入数据库:
        // $db->insert('user_table', [
        //     'id' => $user['id'],
        //     'displayName' => $user['displayName'],
        //     'mail' => $user['mail']
        // ]);
    }
}

关键优化点

  1. 调大每页数据量:用top(999)设置每页最大支持的999条数据,把请求次数从500次(默认100条/页)降到51次,大幅减少网络开销。
  2. 逐页释放内存:处理完每页数据后,手动unset响应对象,避免内存堆积。
  3. 按需处理数据:如果你的业务不需要把所有数据都放在内存里(比如同步到数据库、生成报表),这种逐页处理的方式能把内存占用控制在几MB以内,效率提升非常明显。

特殊场景补充

如果你确实需要把所有数据都保存在内存中(比如后续要做全局排序、统计),那可能还是需要合并数组,但可以优化合并方式:用$docs = [...$docs, ...$docGrabber->getPage()]替代array_merge,PHP的展开运算符性能比array_merge更高。不过这种情况还是建议尽量避免,5万条数据存在内存里没必要。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:20:37