在我的项目中,我有一个 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/