在我的项目中,我有一个API调用,可能会返回数万条记录.
数据应该在一个块中返回. 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"');
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。