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'] // ]); } }
关键优化点
- 调大每页数据量:用
top(999)设置每页最大支持的999条数据,把请求次数从500次(默认100条/页)降到51次,大幅减少网络开销。 - 逐页释放内存:处理完每页数据后,手动
unset响应对象,避免内存堆积。 - 按需处理数据:如果你的业务不需要把所有数据都放在内存里(比如同步到数据库、生成报表),这种逐页处理的方式能把内存占用控制在几MB以内,效率提升非常明显。
特殊场景补充
如果你确实需要把所有数据都保存在内存中(比如后续要做全局排序、统计),那可能还是需要合并数组,但可以优化合并方式:用$docs = [...$docs, ...$docGrabber->getPage()]替代array_merge,PHP的展开运算符性能比array_merge更高。不过这种情况还是建议尽量避免,5万条数据存在内存里没必要。
内容的提问来源于stack exchange,提问作者sipher_z
相关产品推荐
相关产品推荐

