CodeIgniter の DB_Driver (save_queries) にご注意【vol.2】

[CodeIgniter の DB_Driver (save_queries) にご注意【vol.1】](https://qiita.com/terra_yucco/items/605fdd7c47c30d2fd707) の続きです。

実コードで実際のオブジェクトのダンプやメモリ使用量を比較してみたのでそのメモを。

昔に作ったローカル環境なので CodeIgniter は 2.0.3 が入っていますが、該当の部分のコードは最新でも大きく変わっていません。

# 実測編
## 使用コード

```php:memory.php
<?php
if (!defined('BASEPATH')) {
    exit('No direct script access allowed');
}

/**
 * Class Memory
 *
 * @property Memory_model memory_model
 */
class Memory extends MY_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->load->model('memory_model');
        echo memory_get_peak_usage(true) . PHP_EOL;
        echo memory_get_peak_usage(false) . PHP_EOL;
    }

    public function index()
    {
        $db = $this->load->database('local', true);
        $this->memory_model->getConfig($db);
    }

    public function index2()
    {
        $this->memory_model->getConfig2();
    }

    public function __destruct()
    {
        echo memory_get_peak_usage(true) . PHP_EOL;
        echo memory_get_peak_usage(false) . PHP_EOL;
    }
}
```

```php:memory_model.php
<?php
if (!defined('BASEPATH')) {
    exit('No direct script access allowed');
}

/**
 * Class memory_model
 *
 * @property CI_Loader load
 */
class memory_model extends MY_Model
{
    private $limit = 1;
    private $max = 1000;

    public function getConfig($db)
    {
        $offset = 0;
        while (true) {
            $db->limit($this->limit)->offset($offset)->get('hoge1_data_master_table')->result_array();
            $offset += $this->limit;
            if ($offset >= $this->max) {
                break;
            }
        }
        var_dump($db);
        echo $db->last_query() . PHP_EOL;
    }
    public function getConfig2()
    {
        $offset = 0;
        while (true) {
            $db = $this->load->database('local', true);
            $db->limit($this->limit)->offset($offset)->get('hoge1_data_master_table')->result_array();
            $offset += $this->limit;
            if ($offset >= $this->max) {
                break;
            }
        }
        var_dump($db);
        echo $db->last_query() . PHP_EOL;
    }
}
```

## 計測コマンド

```
$ time php /path/to/root/htdocs/index.php memory/index
$ time php /path/to/root/htdocs/index.php memory/index2
```

## 実行結果
途中は長いので略しています。

### サマリ

単純な短いクエリですが、発行クエリと実行時間が　1,000 回記録されるので、さすがにメモリ使用量に差が出てきています。
また、毎回 DB に接続をしなおすので、オブジェクトを保持しない場合には、明らかに処理が遅くなっています。
save_queries を true にしているので `last_query()` で結果を表示できています。

type|real|user|sys|peak(true)|peak(false)
:--|:--|:--|:--|:--|:--
DB オブジェクト保持型|0m3.821s|0m0.698s|0m0.162s|8,388,608|8,155,616
DB オブジェクト非保持型|0m10.503s|0m1.143s|0m1.107s|7,864,320|7,800,056


### DB オブジェクト保持型 (index)

```terminal
7602176
7508336

class CI_DB_mysqli_driver#30 (73) {

:

  public $save_queries =>
  bool(true)
  public $queries =>
  array(1000) {
    :
    (more elements)...
  }
  public $query_times =>
  array(1000) {
    :
    (more elements)...
  }

:

}
SELECT *
FROM (`hoge1_data_master_table`)
LIMIT 1 OFFSET 999
8388608
8158160

real    0m3.821s
user    0m0.698s
sys     0m0.162s
```

### DB オブジェクト非保持型 (index2)

```terminal
7602176
7508336

class CI_DB_mysqli_driver#30 (73) {

:

  public $save_queries =>
  bool(true)
  public $queries =>
  array(1) {
    [0] =>
    string(60) "SELECT *
FROM (`hoge1_data_master_table`)
LIMIT 1 OFFSET 999"
  }
  public $query_times =>
  array(1) {
    [0] =>
    double(0.0046629905700684)
  }

:

}
SELECT *
FROM (`hoge1_data_master_table`)
LIMIT 1 OFFSET 999
7864320
7800056

real    0m10.503s
user    0m1.143s
sys     0m1.107s
```

## save_queries = false
### サマリ

同じコードで `save_queries` だけを false に設定したところ、メモリの使用量に差はなくなりました。この場合は、DB 接続を作り直すほうが時間だけかかるので、オブジェクトは保持したほうがよさそうです。
`last_query()` の結果は表示されなくなりました。

type|real|user|sys|peak(true)|peak(false)
:--|:--|:--|:--|:--|:--
DB オブジェクト保持型|0m3.979s|0m0.639s|0m0.193s|7,864,320|7,772,392
DB オブジェクト非保持型|0m9.320s|0m1.046s|0m1.160s|7,864,320|7,799,760

### DB オブジェクト保持型 (index)

```
7602176
7509808
class CI_DB_mysqli_driver#30 (73) {

:

  public $save_queries =>
  bool(false)
  public $queries =>
  array(0) {
  }
  public $query_times =>
  array(0) {

:

}

7864320
7772392

real    0m3.979s
user    0m0.639s
sys     0m0.193s
```

### DB オブジェクト非保持型 (index2)

```
7602176
7509808
class CI_DB_mysqli_driver#30 (73) {

:

  public $save_queries =>
  bool(false)
  public $queries =>
  array(0) {
  }
  public $query_times =>
  array(0) {
  }

:

}

7864320
7799760

real    0m9.320s
user    0m1.046s
sys     0m1.160s
```