CakePHP2のパフォーマンスチューニング（DBとキャッシュ）

# CakePHPにおけるパフォーマンスチューニングとは
パフォーマンス向上するための方法は大まかに分けて２種類ある
### 1. ボトルネックとなる処理を探し当てて改善する方法
コードを修正する、パラメータをチューニングするなど。
### 2. キャッシュを使う方法
処理実行結果をキャッシュに保存することで、2回目にアクセスしたときにその処理を通らずに処理結果を返す事ができる。



# DBのパフォチュー

## 1. 発行しているクエリ数を減らす

```
<?php echo $this->element('sql_dump'); ?>
```

これをViewに貼ればカウントできる。減らせるクエリは減らす。


## 2. findのパフォチュー

極力以下を利用する。


### a) 基本的にqueryメソッドが最強。ただし...

コードの可読性が下がるので大量データを取得する必要があるときに利用。場合によってはfieldで取得するより早い。

✕ `$this->Hoge->find('all');`
◯ `$this->Hoge->query('SELECT * FROM .....')`


[公式ドキュメント](http://book.cakephp.org/2.0/ja/models/retrieving-your-data.html#model-query)


#### queryメソッドの注意点
同一リクエスト内で同じ内容のクエリメソッドを複数回実行すると、一回目のクエリがキャッシュされるため、一回目以降の実行時の結果はかならず一回目のものと同一になる。

それが嫌なら第二引数にfalseをセットすべし





### b) 次点でfieldメソッド

条件にマッチした特定のフィールドのデータのみ取得

`$this->Model->field('カラム名', $conditions, $order)`


[公式ドキュメント](http://book.cakephp.org/2.0/ja/models/retrieving-your-data.html#model-field)



### c) それ以外はfind。findByXxxxxは使わない

findByIdとかfindAllByIdを使うより、普通のfindを使った方が早い。

#### findを利用するときの注意点
* 使っても良い順: `first > count > limit >>>>> all`
* 関係ないデータを取得しないようにかならず `recursive` を設定する
* allを使うときは可能なら `limit` を設定する
* どんなクエリを発行してるか確認する




## 3. まだsaveAllで消耗してるの？

saveAllは地雷です。忘れましょう。 **saveをforeachした方が早い。**


可読性より性能を重視したい箇所ではsaveやsaveAll、updateAllは基本的に使わず、代わりにqueryメソッドを使います。


とある記事の実行結果では以下のようになったらしい

![スクリーンショット 2016-06-17 17.04.00.png](https://qiita-image-store.s3.amazonaws.com/0/18614/2a09919d-77b2-9d9c-8122-ff9faf5e42a8.png "スクリーンショット 2016-06-17 17.04.00.png")

[（参考）CakePHP2.x系でバルクインサートを使用して高速なインサート処理を実現する](http://damepg.hatenablog.com/entry/2012/10/01/001223)




もちろん、可読性は高いので、パフォチューが必要ない場所では使っていいよ。


# キャッシュのパフォチュー

これうまいこと活用すればすごいパフォーマンスあがるよ！


## Cacheクラスを利用

### 準備

キャッシュを利用するクラス内でCacheクラスを読み込む

```
App::uses('Cache', 'Cache');
```


### キャッシュの書き込み

```
Cache::write($key, $value, $config = 'default');
```

第三引数のキャッシュの設定は省略可能

### キャッシュの読込

```
Cache::read($key, $confitg = 'default');
```
有効期限が切れてたりエラーが起こるとfalseが返ってくる


### キャッシュの削除

```
Cache::delete($key, $confitg = 'default');
```



### 使い方

```
public function doSomething() {
	$ret = Cache::read('hoge');
	if($ret !== false) {
	    return $ret;
	}
	$ret = $this->Hoge->find('first');
	Cache::write('hoge', $ret);
	return $ret
}
```



## Viewキャッシュのパフォチュー
### Viewのキャッシュ時間を設定する

アクションごとに設定できる。


#### core.phpにて

```
Configure::write('Cache.check', true); // コメント外す
```


#### Controllerにて
* キャッシュを利用するViewに対応するControllerにてキャッシュヘルパーを指定

```
public $helpers = ['Cache'];
```


* 以下のように `cacheAction` を設定することでビュー出力を時間分キャッシュする

```
public $cacheAction = [
    'index' => '+1 hour', 
    'view' => '+10 minute'
];
```


### 部分的にViewキャッシュから除外する
Viewの中で以下のタグを入れればリクエストごとに表示処理が実行される。（リクエストごとにPHPを実行したい場合などに利用）

```
<!--nocache-->
キャッシュしたくない箇所
<!--nocache-->
```

### Viewキャッシュの削除
以下の3つの場合に削除される
#### 1. 定めた有効期間を過ぎた場合

#### 2. Modelのsaveメソッドもしくはdeleteメソッドを実行した場合
この場合自動でViewキャッシュが削除される。削除されるのはModelの名前に合致するViewキャッシュ。たとえばHogeモデルのsaveメソッドを実行するとHogesコントローラーのViewキャッシュが削除される。

#### 3. clearCache関数を実行した場合

```
// すべてのViewキャッシュを削除
clearCache();

// HogesコントローラーのViewキャッシュを削除
clearCache('hoges');

```



### Elementをキャッシュする

```
echo $this->element('helpbox', array(), array('cache' => true));
```

[（公式）エレメントをキャッシュする](http://book.cakephp.org/2.0/ja/views.html#id10)



[（参考）Viewをキャッシュする](http://www.happytrap.jp/blogs/2012/04/01/8646/)




# その他のパフォチュー
## `$this->Html->link();` は地雷
地味に思いよ。Htmlヘルパーのlinkメソッドは全てhtmlに置き換えよう。




# (おまけ)処理速度計測の方法

以下のコードで囲えば処理にかかった秒数がログ出力されるよ！

```php:
$start = microtime(true);

/* ここの処理を計測！ */

$end = microtime(true) - $start;
$this->log($end); //ログ出力
```