34
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CakePHPのModel->query()でSQLを何回も発行するようなバッチを作る際の注意点

Posted at

ほとんどこんな事例ないと思うけど、メモ。

CakePHPでバッチを作る際に、Model->query()でSQLを何回も発行するような組み方をしてしまうと、メモリが足りなくて処理落ちする事がある。まぁ、そもそもこんなバッチ組んでるのどうなの?って思うけど。

<?php
class HogeShell extends AppShell {
	public $uses  = array('Hoge');
	public function main() {
		for ($i=0; $i<100; $i++) {
			// メモリ足りなくて死ぬ
			$result = $this->Hoge->query('...');
		}
	}
}

前提

  • CakePHP 2.4.x

Model->find() などはクエリキャッシュできる

Modelにはセッション単位でのクエリキャッシュする機能がある。Model-> cacheQueries に true を設定すると、クエリキャッシュが有効になる。デフォルトでは無効。あくまでセッション単位なので、活用するシーンはあまりなさそうだけど。

Hoge.php
<?php
class Hoge extends AppModel {
	public $cacheQueries = true;
}

Model->query()はデフォルトでクエリキャッシュする

まさにこれがハマリポイント。

query() は本質的に分離された機能のため、$Model->cacheQueries は無視されます。クエリ実行のキャッシュしないようにするには、2つ目の引数にfalseを指定してください。query($query, $cachequeries = false)

マニュアルにしっかり書かれているが、特別扱いのため、別個で指定してあげないとNG。それにしてもなぜModel->query()はデフォルトでクエリキャッシュが有効なのか。謎。

lib/Cake/Model/Datasource/DboSource.php
public function fetchAll($sql, $params = array(), $options = array()) {
		if (is_string($options)) {
			$options = array('modelName' => $options);
		}
		if (is_bool($params)) {
			$options['cache'] = $params;
			$params = array();
		}

		// ここで無指定ならデフォルトで有効にしている…
		$options += array('cache' => true);
		$cache = $options['cache'];

		// snip
}

なので、クエリキャッシュする必要がなく、何回もquery()を実行する場合は、引数に false を渡してあげよう。

<?php
class HogeShell extends AppShell {
	public $uses  = array('Hoge');
	public function main() {
		for ($i=0; $i<100; $i++) {
			// メモリ足りて無事終わる
			$result = $this->Hoge->query('...', false);
		}
	}
}

そして、こういったバッチを書いている状況の場合、もっと改善できないか検討しよう。

34
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?