大量データを INSERT すると、どうしても処理が遅くなります。
INSERT into SELECT でも対応できる場合、INSERT into SELECT にすることで速度を改善できます。
この記事でわかること
- CakePHP4 での INSERT into SELECT のやり方
バージョン情報
バージョン | |
---|---|
CakePHP4 | 4.0.5 |
参考サイト
試し用テーブル
INSERT into SELECT を試すために以下の2つのテーブルを用意します。
tasks テーブルの内容を copy_tasks テーブルへコピー(INSERT into SELECT)するテーブルです。
PrimaryKey は uuid で採番します。
copy_tasks テーブルには、copied したことをマークするフラグを持たせいて、これはコピー時に常に 1 をセットします。
<?php
declare(strict_types=1);
use Migrations\AbstractMigration;
class CreateTasks extends AbstractMigration
{
/**
* Change Method.
*
* More information on this method is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-change-method
* @return void
*/
public function change(): void
{
$this->table('tasks', ['id' => false, 'primary_key' => ['id']])
->addColumn('id', 'uuid', ['default' => null, 'null' => false])
->addColumn('description', 'text', ['default' => null, 'limit' => null, 'null' => false])
->addColumn('created', 'datetime', ['default' => 'CURRENT_TIMESTAMP', 'limit' => null, 'null' => false])
->addColumn('modified', 'datetime', ['default' => 'CURRENT_TIMESTAMP', 'update' => 'CURRENT_TIMESTAMP', 'limit' => null, 'null' => false])
->create();
}
}
<?php
declare(strict_types=1);
use Migrations\AbstractMigration;
class CreateCopyTasks extends AbstractMigration
{
/**
* Change Method.
*
* More information on this method is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-change-method
* @return void
*/
public function change(): void
{
$this->table('copy_tasks', ['id' => false, 'primary_key' => ['id']])
->addColumn('id', 'uuid', ['default' => null, 'null' => false])
->addColumn('description', 'text', ['default' => null, 'limit' => null, 'null' => false])
->addColumn('copied', 'boolean', ['default' => null, 'limit' => null, 'null' => false])
->addColumn('created', 'datetime', ['default' => 'CURRENT_TIMESTAMP', 'limit' => null, 'null' => false])
->addColumn('modified', 'datetime', ['default' => 'CURRENT_TIMESTAMP', 'update' => 'CURRENT_TIMESTAMP', 'limit' => null, 'null' => false])
->create();
}
}
INSERT into SELECT
INSERT するために SELECT するカラムを select()
します。
id は MySQL で uuid を採番します。CakePHPの func()
メソッドには ( https://book.cakephp.org/4/en/orm/query-builder.html#using-sql-functions )、 uuid()
は定義されていませんが、定義されていない場合、直接DBの関数を呼び出すようになっているので、問題なく動きます。
description は tasksテーブルのレコード内容を使います。
copied は 常に 1
をセットします。
$Tasks = $this->getTableLocator()->get('Tasks');
$CopyTasks = $this->getTableLocator()->get('CopyTasks');
$select = $Tasks->find();
$select = $select->select([$select->func()->uuid(), 'description', 1])
->limit(5);
$CopyTasks->query()
->insert(['id', 'description', 'copied'])
->values($select)
->execute();
実際に発行される SQL は以下です。
INSERT INTO copy_tasks (id, description, copied) SELECT (uuid()), Tasks.description AS Tasks__description, 1 FROM tasks Tasks LIMIT 5