php - 流式传输大型 Doctrine 2 查询结果以输出

标签 php mysql performance doctrine-orm doctrine

在我的项目中,我有一个 API 调用可能会返回数万条记录。

数据应该以一个 block 的形式返回。 API 设计不允许分页。

源数据是使用 Doctrine 2 DQL 从 MySQL 查询的,每条记录由多个链接对象组成。目前查询结果约为 25'000 条记录。我已经优化了 SQL 查询。它在几毫秒内运行,因此无法在此处进行优化。

现在的主要问题是补水。我已经尝试了不同类型的水合作用,但处理这些数据量仍然需要很长时间。它还占用了太多内存。

我的想法是数据一被水合就流式传输,然后一流式传输就删除数据。它不会减少完成请求的时间,但会减少内存使用并减少响应开始前的时间。

Doctrine 2 中是否有一种方法可以在每个结果行被水合后执行一些操作?

即我提出了很大的要求。我执行 $qb->getQuery()->getResult() 和 Doctrine 而不是对所有数据进行水化并在每个记录被水化后返回结果将数据发送到例如 STDOUT 并在数据完成后立即删除对象流式传输。

PS:问题不是关于如何将此类查询的输出流式传输到 HTTP。我能应付。问题是关于如何让 Doctrine 2 做我想做的事。

最佳答案

我的解决方案(包括 CSV 流以确保完整性):

function getExportableHead()
{
    // returns array of fields for headings
}

function getExportableRow($row)
{
    // returns array of values for a row
}

$qb = $this->em->getRepository(Item::class)->createSomeQueryBuilder();
$response = new StreamedResponse(function () use ($qb) {
    $data = $qb->getQuery()->iterate();
    $handle = fopen('php://output', 'w+');
    fputcsv($handle, getExportableHead(), ';');
    while (($object = $data->next()) !== false) {
        $row = getExportableRow($object[0]);
        fputcsv($handle, $row, ';');
        $this->em->detach($object[0]);
    }
    fclose($handle);
});
$response->headers->set('Content-Type', 'text/csv; charset=utf-8');
$response->headers->set('Content-Disposition', 'attachment; filename="out.csv"');

关于php - 流式传输大型 Doctrine 2 查询结果以输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36866671/

相关文章:

php - Phinx 迁移 sqlite 内存 phpunit

PHP 将数据从一个表插入到另一个表

PHP 在 MAMP 中不显示任何内容

c# - 我可以改进嵌入式 C# 上的 "double.IsNaN( x )"函数调用吗?

Asp.net 应用程序很慢但 CPU 最大为 40%

php - 在代理后面使用 Predis 连接到 Redis

javascript - 如何获取 PHP SDK 中 gen_results_table 返回的字符串并将其转换为 Javascript 数组?

PHP FOR迭代不迭代

javascript - 如何将带有日期的 JSON 文件加载到 Google Charts

performance - 响应式 CSS 设计——从大屏还是小屏开始