PHPのフレームワークのCodeigniterでツールを開発して思ったことです。
負荷テストをするために、大量にデータをInsertして動作確認をしていたところ、SQLに怪しいところがありました。
「num_rows()」を使うとメモリ不足になる
データベースからデータを取得するためにnum_rows()を使用してページング機能の実装していたのですが、num_rows()を呼び出すことでSQLで「select count(*) from table_name;」をしてくれていると思っていました。
しかし、そうではないらしく実際は下記のsqlが発行されています。
select * from table_name;
つまりcountの件数を取得しているのではなくデータをいったん取得してPHP内で件数だけ返しているようです。
そして、当たり前ですが下記のエラーが発生します。
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4096 bytes) in C:\xampp\htdocs\project\system\database\drivers\sqlite3\sqlite3_result.php on line 142
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4096 bytes) in C:\xampp\htdocs\project\system\core\Common.php on line 163
「num_rows()」はあくまでクエリで返された行数を返す役割であって、SQL発行時に「select count(*) from table_name;」をしているわけではないということです。
Codeigniter3のDB関連の記事を読んでると、勘違いしている人多い気がします。
データ量が少なければさほど影響はないかもしれませんが、10万単位でデータを操作するとかなり重たいし、メモリ不足エラーも発生します。
解決方法
データベースから件数を取得したい場合は、下記のように対処することができます。
1 2 3 4 5 | // 件数を取得 $result = $this->db->select('count(*) as count')->get("table_name")->row(); //件数 var_dump($result->count); |
SELECT部分でAS句を使ってカラム名を指定しとかないと、後でデータ取得ができません。
デバッグのSQLログを確認しよう
Codeigniter3にはデバッグモードにするとSQLログを画面上に表示してくれるのでそこで確認しましょう。

最後に
公式サイトにもちゃんと書かれていますね。
num_rows()
クエリで返された行数を取得します。Note: 下記の例では $query は、クエリの結果オブジェクトを代入した変数です:
公式サイトを見ずにメソッド名だけで判断するのは危険て言うことを今回学習しました。
コメントを残す