流式传输大型教义2查询结果以输出

Ste*_*hka 3 php mysql performance doctrine doctrine-orm

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

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

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

现在的主要问题是水合作用。我尝试了不同类型的水合作用,但在该数量的数据上仍然花费太长时间。它还占用太多内存。

我的想法是在数据被水合后立即流化,然后在数据被流化后立即删除数据。它不会减少完成请求的时间,但会减少内存使用量,并减少响应开始之前的时间。

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

即,我提出了很大的要求。我会这样做,$qb->getQuery()->getResult()而Doctrine则不会合并所有数据并在每个记录被合并后返回结果,而是将数据发送到例如STDOUT并在流式传输数据后立即丢弃对象。

PS:问题不是关于如何将此类查询的输出流式传输到HTTP。我可以解决。问题是我怎样才能使教义2做我想做的事。

Pie*_*NAY 5

我的解决方案(包括完整性的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"');
Run Code Online (Sandbox Code Playgroud)