簡體   English   中英

學說插入許多數據

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM