在我的项目中,我有一个API调用,它可能会返回数万条记录。
数据应该以一个块的形式返回。API设计不允许分页。
使用Doctrine 2DQL从MySQL查询源数据,每个记录由几个链接的对象组成。目前,查询结果大约是25'000条记录。我已经优化了SQL查询。它在毫秒内运行,所以无法在这里进行优化。
现在主要的问题是水合作用。我尝试过不同类型的hydrations,但处理这些数据量仍然需要很长时间。它也使用了太多的内存。
我的想法是在数据被加水后立即流式传输,然后在流式传输时立即删除数据。它不会减少完成请求的时间,但会减少内存使用,并减少响应开始前的时间。
在Doctrine 2中,有没有一种方法可以在每个结果行加水后执行一些操作?
也就是说,我做了一个大请求。我做了$qb->getQuery()->getResult()和Doctrine,而不是合并所有数据并在每条记录合并后返回结果,例如,将数据发送到STDOUT,并在数据被流式传输时立即删除对象。
PS:问题不是关于如何将此类查询的输出流式传输到HTTP。我能处理好。问题是我如何才能让Doctrine 2做我想做的事情。
发布于 2017-01-16 18:55:15
我的解决方案(包括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"');https://stackoverflow.com/questions/36866671
复制相似问题