大数据库-即使有索引也很慢

kfgdxczn  于 2021-06-17  发布在  Mysql
关注(0)|答案(2)|浏览(395)

我正在用symfony4+理论构建一个应用程序,人们可以上传大的csv文件,然后这些记录被存储在数据库中。在插入之前,我正在检查条目是否已经存在。。。
对于一个只有1000条记录的示例csv文件,没有索引需要16秒,索引需要8秒(macbook 3ghz-16gb内存)。我的直觉告诉我,这是相当缓慢的,应该在<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();
    }
}

我的问题是:
如何加快这一进程?

2g32fytz

2g32fytz1#

使用加载数据填充。
加载数据填充 IGNORE 以及 REPLACE 如果您将 UNIQUE KEY 或者 PRIMARY KEY 在你的 email 列。
请查看使导入更快的设置。

a64a0gku

a64a0gku2#

就像cid所说的,将flush()移到循环外,或者在循环内放置一个批处理计数器,并且只在特定的时间间隔内对其内部进行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();

或者如果速度仍然很慢,你可以抓住连接 $this->em->getConnection() 并使用dbal,如下所述:https://www.doctrine-project.org/projects/doctrine-dbal/en/2.8/reference/data-retrieval-and-manipulation.html#insert

相关问题