Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

CodeIgniter の DB_Driver (save_queries) にご注意【vol.1】 の続きです。

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

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

実測編

使用コード

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;
    }
}
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)

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)

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
terra_yucco
株式会社オズビジョンでサーバサイドエンジニアとして勤務しているユッコ (テラシマユウコ) です。IPA の情報処理技術者試験で資格を取りまくっていた時期があり FE/AP/SA/DB/ES/SC(旧区分時代:情報セキュリティスペシャリスト) を取得済。
ozvision
購買プラットフォーム「ハピタス」を開発・運営するベンチャー企業
https://www.oz-vision.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away