2013年5月3日金曜日

[CakePHP]Database

Cache を利用して DB へのアクセスを減らす
Table: exams テーブル
iduser_idmathenglishphysics
11493656
22454842
33728091
上記の exams テーブルにアクセスして表を作成し、さらにそのデータから JpGraph でグラフを作成する場合 ExamsController に表を作成するための関数をグラフを作成するための関数を準備する必要がある。
function exam_total() {
 $users = $this->User->find('all');
 foreach ($users as $user) {
  $total[$user['User']['id']] = 0;
  $total[$user['User']['id']] = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];
 }
 $this->set('users', $users);
 $this->set('total', $total);
 $this->set('graph_path', './exam_total_graph');
}

function exam_total_graph() {
 /* JpGraph を使用する */
 App::import('Vendor', 'jpgraph/jpgraph');
 App::import('Vendor', 'jpgraph/jpgraph_bar');

 /* DB から値を取得 */
 $users = $this->User->find('all');

 $y1data = array();
 $y2data = array();
 $zerodata = array();

 $a = array();

 /* 合計計算 */
 foreach ($users as $user) {
  $total = 0;
  $total = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];

  array_push($y1data, $user['Exam']['math']);
  array_push($y2data, $total);
  array_push($zerodata, 0);
  array_push($a, $user['User']['username']);
 }

 /* グラフ作成 */
 $graph = new Graph(350, 250, "auto");
 $graph->SetScale("textlin", 0, 100);
 $graph->SetY2Scale("lin", 0, 300);
 /* 右側の Y 軸で値が全部表示できないのでグラフを表示する場所の
  * margin を指定する
  */
 $graph->img->SetMargin(30, 30, 30, 30);

 /* X軸項目追加 */
 $graph->xaxis->SetTickLabels($a);

 /* plot作成 */
 $bplot1 = new BarPlot($y1data);
 $bplot1->value->Show();
 $bplot1->value->SetFormat('%d');

 $bplot2 = new BarPlot($y2data);
 $bplot2->value->Show();
 $bplot2->value->SetFormat('%d');

 /* 単純に bplot1, bplot2 を表示するとグラフが重なってしまうので
  * $zerodata のダミーを間に挟んでグループ化して
  * bplot1, bplot2 が並んでいるように表示する
  */
 $bplotzero = new BarPlot($zerodata);
 $bgplot1 = new GroupBarPlot(array($bplot1, $bplotzero));
 $bgplot2 = new GroupBarPlot(array($bplotzero, $bplot2));

 /* グラフ上に描画 */
 $graph->Add($bgplot1);
 $graph->AddY2($bgplot2);

 /* グラフ表示 */
 $graph->Stroke();
}
この中で DB にアクセスして値を格納し、各人の合計得点を計算する箇所が重複している
$users = $this->User->find('all');
foreach ($users as $user) {
  $total[$user['User']['id']] = 0;
  $total[$user['User']['id']] = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];
}
Cache 機能を使うことで DB へのアクセスを減らすことが可能となる。
Cache::read($key, $config = null);
Cache::write($key, $value, $config = null);
Cache::delete($key, $config = null);
  • write() で $key に入力した文字列に $value の値を関連付けて保存する。
  • read() で $key に関連付けられた値を読み込む。
  • delete() で $key の値を cache から削除する。
$config は Cache 機能の設定ファイルを指定する。null の場合はデフォルト設定が使用される。
function exam_total() {
 $users = $this->User->find('all');

 foreach ($users as $user) {
  $total[$user['User']['id']] = 0;
  $total[$user['User']['id']] = $user['Exam']['math'] + $user['Exam']['english'] + $user['Exam']['physics'];
 }

 $this->set('users', $users);
 $this->set('total', $total);
 Cache::write('users', $users);
 Cache::write('total', $total);
}

function exam_total_graph() {
 /* JpGraph を使用する */
 App::import('Vendor', 'jpgraph/jpgraph');
 App::import('Vendor', 'jpgraph/jpgraph_bar');

 /* Cache に保存された値を読み込む */
 $users = Cache::read('users');
 $total = Cache::read('total');

 Cache::delete('users');
 Cache::delete('total');

 $y1data = array();
 $y2data = array();
 $zerodata = array();
 $a = array();

 foreach ($users as $user) {
  array_push($y1data, $user['Exam']['math']);
  array_push($y2data, $total[$user['User']['id']]);
  array_push($zerodata, 0);
  array_push($a, $user['User']['username']);
 }

 (以下略)
  • exam_total() の最後で $users, $total を Cache に保存しておき、exam_total() の後に呼び出される exam_total_graph() では cache のデータを利用するように変更して DB へのアクセス回数を減らすことができる。
  • Cache::write() により app/tmp/cache 以下に cake_total, cake_users というファイルが生成される。これを exam_total_graph() 関数で Cache::read() により読み出し、読み出し後は Cache::delete() で削除する。

0 件のコメント:

コメントを投稿