[英]Doctrine insert many data
我正在許多csv中導入300000行。
首先,我將csv導入到數據庫內部的表中。
之后,我想解析所有行並插入與該數據有某種關系的正確表中。
所以我嘗試了這個:
$qb = $this->entityManager->createQueryBuilder();
$flows = $qb->select('flow')
->from('AppBundle:FlowAndata', 'flow')
->getQuery()
->getResult();
$countRows = 0;
foreach ($flows as $row) {
//some check
$entity = new TestTable();
$entity->setCode($row->getCode());
//many other fields
$this->entityManager->persist($entity);
$this->entityManager->flush();
}
在這種情況下,每一行所有過程大約需要5秒鍾!
現在,如果我添加setMaxResults像這樣:
$qb = $this->entityManager->createQueryBuilder();
$flows = $qb->select('flow')
->from('AppBundle:FlowAndata', 'flow')
->setMaxResults(100)
->getQuery()
->getResult();
花了不到1秒!
所以我想過要獲取所有行,並使用setMaxResult將其拆分為遞歸函數,如下所示:
$qb = $this->entityManager->createQueryBuilder();
$flows = $qb->select('flow')
->from('AppBundle:FlowAndata', 'flow')
->getQuery()
->getResult();
$countFlows = count($flows);
$numberOfQuery = $countFlows / 100;
for ($i = 0; $i <= $numberOfQuery; $i++) {
$this->entityManager->clear();
$qb = $this->entityManager->createQueryBuilder();
$flows = $qb->select('flow')
->from('AppBundle:FlowAndata', 'flow')
->setFirstResult($i * 100)
->setMaxResults(100)
->getQuery()
->getResult();
}
這樣,我創建了許多查詢,這些查詢分為100行。 是好的做法,還是有更好的方法來解析許多行並插入It?
Doctrine的官方文檔推薦的一種有效方法是利用EntityManager
的事務后寫行為。
迭代大結果以進行數據處理
您可以使用
iterate()
方法來迭代較大的結果,而無需執行UPDATE或DELETE意圖。 從$query->iterate()
返回的IterableResult
實例實現了Iterator接口,因此您可以使用以下方法處理較大的結果而不會出現內存問題。 ( 請參見示例 )
批量插入
利用
EntityManager
的事務后寫行為,最好在批處理中批量進行最佳插入。 [...]您可能需要嘗試批量大小以找到最適合您的大小。 較大的批處理大小意味着內部准備好的語句重用率更高,但也意味着flush
期間需要進行更多工作。 ( 請參見示例 )
版本混合兩種技術 (內部實體存儲庫中):
$q = $this->_em->createQuery('SELECT f FROM AppBundle:FlowAndata f');
$iterableResult = $q->iterate();
$i = 0;
$batchSize = 100;
foreach ($iterableResult as $row) {
// do stuff with the data in the row, $row[0] is always the object
/** @var AppBundle\Entity\FlowAndata $flow */
$flow = $row[0];
//some check
$entity = new TestTable();
$entity->setCode($row->getCode());
//many other fields
$this->_em->persist($entity);
$i++;
if (($i % $batchSize) === 0) {
$this->_em->flush();
// Detaches all objects from Doctrine!
$this->_em->clear();
} else {
// detach from Doctrine, so that it can be Garbage-Collected immediately
$this->_em->detach($flow);
}
}
$this->_em->flush(); //Persist objects that did not make up an entire batch
$this->_em->clear();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.