ラベル symfony の投稿を表示しています。 すべての投稿を表示
ラベル symfony の投稿を表示しています。 すべての投稿を表示

2015年8月20日木曜日

Symfony 1.4でDQLをSQLにパース

Symfony 1.4をDoctrineで使っているアプリケーションで、もともとDQLのものを生SQLにしたいことがあったので、調べていたところ、パース方法をまとめているのを見つけました!

Raw SQL from Doctrine Query Object - Revised
http://insidethe.agency/blog/raw-sql-from-doctrine-query-object-revised

このサイトの記事自体が古いので、split()を使っているのですがPHP 5.3.0からは非推奨になっているため、preg_split()に書き換えると問題なく動きます!

$query_str_parts = preg_split('/\?/', $query_str);

こんな感じです!

更に、カラム名のリネームを削除したい場合は、preg_splitの前(16行目)に下記を追加するとできます。

$query_str = preg_replace('/AS\s\`[0-9a-z!-~]*\`/', '', $query_str);

リファレンスを確認しつつ、パースできないかやっているときに発見したので、とても助かりました。

2014年12月3日水曜日

Symfony1.4のDoctrineで大量のデータ操作をした時に Allowed memory size...のエラーになる

Symfony1.4のDoctrineで、1万件くらいのデータを取り出してforeachで1件ずつ更新しようとしたところ、Allowed memory size..のエラーがでてしまいました。

PHP Fatal error:  Allowed memory size of 536870912 bytes exhausted (tried to allocate 32 bytes)

このエラーが出た時は、php.iniのmemory_limitを変更すれば、防げるようになるのですが、php.iniを変更できなかったり、変更したくないことも多いと思います。。

今回は、php.iniを変更したくなかったので、設定以外で対応したいと思っていたところ、Doctrineにはfree()というものがあり、オブジェクトを解放できることがわかりました。

free()は、Doctrine_RecordとDoctrine_Query、Doctrine_Collectionで使うことができるみたいです。

試しにテーブルから5000件抽出し、ループでupdated_atカラムを更新するプログラムを実行してみました。

// Usersテーブルから5000件のデータを抽出
$q = Doctrine_Query::create()
     ->from('User u')
     ->limit(5000)
     ->orderBy('u.id ASC')
     ->execute();

foreach ($q as $k => $val) {
      $val->updated_at = date("Y-m-d H:i:s");
      $val->save();
      if ($k % 500 == 0){
            printf("%d : %dKB\n", $k, (memory_get_usage(true) / 1024));
      }
      $val->free();
}
$q->free();
printf("End : %dKB\n", $k, (memory_get_usage(true) / 1024));


効果があるのかを判定するために、まずは$val->free()をコメントアウトして実行してみました。

0        : 94976KB
500   : 99072KB
1000 : 102912KB
1500 : 106752KB
2000 : 111616KB
2500 : 115712KB
3000 : 119552KB
3500 : 123392KB
4000 : 127232KB
4500 : 131840KB
End    : 137728KB

実行結果からもわかるように、メモリがどんどん増えていきます。今回はこれを増えないようにしたいので、$val->free()を有効にして実行してみます。

0       : 94976KB
500   : 95488KB
1000 : 95744KB
1500 : 96000KB
2000 : 97024KB
2500 : 97024KB
3000 : 97024KB
3500 : 97024KB
4000 : 97024KB
4500 : 97536KB
End    : 99584KB

多少は増えますが、なにもしないときよりも38144KBのメモリを抑えることができましたので、大量にデータを扱うときは対策をするべきだなと思いました。

また、テーブルを結合している場合は、引数にtrueを渡してfree(true)と指定することで、リレーションのオブジェクトもすべて解放することができます。

macOSでminikubeをインストールしようとしたら書き込みエラーになった

ローカル環境でKubernetesを使えるようにしようと環境構築中にエラーが 下記が今回のエラーで書き込みできない感じのメッセージが出ています。  $ brew install minikube Updating Homebrew... Error: The following ...