大数据库-即使有索引,学说查询也会变慢

时间:2018-12-12 10:22:10

标签: mysql performance csv doctrine symfony4

我正在用Symfony 4 + Doctrine构建一个应用程序,人们可以在其中上载大的CSV文件,然后将这些记录存储在数据库中。插入之前,我正在检查条目是否不存在...

在仅包含1000条记录的示例CSV文件中,不带索引需要16秒,带索引需要 8秒(MacBook 3Ghz-16 GB内存)。我的直觉告诉我,这很慢,应该在<1秒内完成,尤其是对于索引。

在电子邮件列上设置索引。

我的代码:

$ssList = $this->em->getRepository(EmailList::class)->findOneBy(["id" => 1]);    

foreach ($csv as $record) {
     $subscriber_exists = $this->em->getRepository(Subscriber::class)
        ->findOneByEmail($record['email']);

    if ($subscriber_exists === NULL) {
        $subscriber = (new Subscriber())
            ->setEmail($record['email'])
            ->setFirstname($record['first_name'])
            ->addEmailList($ssList)
        ;

        $this->em->persist($subscriber);
        $this->em->flush();
    }
}

我的问题:

如何加快此过程?

2 个答案:

答案 0 :(得分:1)

使用LOAD DATA INFILE

LOAD DATA INFILE具有IGNOREREPLACE选项,如果您在UNIQUE KEY列上放置PRIMARY KEYemail,则可以处理重复项。

Look at settings用于加快导入速度。

答案 1 :(得分:0)

就像Cid所说的那样,将flush()移到循环外或在循环内放置一个批处理计数器,并且仅以一定的间隔在循环内刷新

$batchSize = 1000;
$i = 1;
foreach ($csv as $record) {
     $subscriber_exists = $this->em->getRepository(Subscriber::class)
        ->findOneByEmail($record['email']);

    if ($subscriber_exists === NULL) {
        $subscriber = (new Subscriber())
            ->setEmail($record['email'])
            ->setFirstname($record['first_name'])
            ->addEmailList($ssList)
        ;

        $this->em->persist($subscriber);
        if (  ($i % $batchSize) === 0) {
            $this->em->flush();
        }
        $i++;
    }
}
$this->em->flush();

或者,如果仍然很慢,则可以抓住Connection $this->em->getConnection()并按照以下说明使用DBAL:https://www.doctrine-project.org/projects/doctrine-dbal/en/2.8/reference/data-retrieval-and-manipulation.html#insert