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做我想做的事。
我的解决方案(包括完整性的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)