Doctrine2 ORM でバルクインサート

Doctrine2 ORM Batch Processing を参考に、バルクインサートを試してみます。

DBスキーマ

mysql> desc mercury;
+--------------+---------------+------+-----+---------+-------+
| Field        | Type          | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+-------+
| recordedDate | varchar(255)  | NO   | PRI | NULL    |       |
| mercury      | decimal(10,2) | NO   |     | NULL    |       |
+--------------+---------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

datetime を主キーにしたら、「Catchable fatal error: Object of class DateTime could not be converted to string」って怒られました。そもそも主キーはプリミティブ型にした方がパフォーマンスが良いそうです。

実装コード

class TestDoctrineOrmBatchProcessingCommand extends ContainerAwareCommand
{
    ...

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $batchSize = 100;
        $dt = new \DateTime('-6 months');
        $em = $this->getContainer()->get('doctrine')->getManager();

        for ($i = 1; $i <= 180; ++$i) {

            $mercury = new Mercury();
            $mercury->setRecordedDate($dt->format('Y-m-d'));
            $mercury->setMercury(rand(15, 35));

            $em->persist($mercury);

            if (($i % $batchSize) == 0) {
                $em->flush();
                $em->clear();
            }

            $dt->modify('+1 day');
        }

        $em->flush();
        $em->clear();

        $em->close();
    }

なお、マルチプルインサートには変換してくれない様ですね。 "a multi-insert is not the best way anyway"とのこと。

おまけ

気象庁のオープンデータ が便利です。