[Codeigniter-users] SELECT count(*) について

Back to archive index

KimuraNobu big-m****@n-k-y*****
2008年 6月 24日 (火) 08:59:47 JST


木村と申します。


>  kunitsujiです。
>
> 追記です。
> ちなみにMyISAMからInnoDBにかえてみました。3000件。
> count(*)でやると、約8倍遅くなります。。
> 0.0024秒。
> SELECT FOUND_ROWS()で取得すると
> 0.0003秒。
> ちなみにプライマリーキーでcount(プライマリー)としてみましたが、
> 3000件程度では変化なし。
>
> アプリケーションでcount(*)をたくさん使っているものが多々ありますが、
> MyISAMからInnoDBに変えた瞬間パフォーマンス下がるということがこれでよくわ
> かりますね。
>

InnoDBは、クラスタインデックスだからでしょうか。
COUNT(*) だとプライマリキーが利用されると思うので、別インデックスを
指定した場合はどうなのでしょうか・・・。


>>櫻井さん。
>>>> よくあるのが、LIMITをつけて取得件数を分けてページネーションするのですが、
>>>> そのときに全体の件数をとる特にCOUNTを使いますが(MyISAMとか)
>>>> num_rowの場合はSQLに対しての件数ですから、LIMITで20件だと20ですね。
>>>今回、まさにこの状況でした。
>>>ページネーションでは全体の件数がいくつか指定する必要があるので、モデルク
>>>ラスに
>>>  ・表示させたいデータをLIMIT, OFFSET付きで取ってくる関数
>>>  ・それとは別に、表示させたいデータの全ての「件数のみ」を取得する関数
>>>を書いて、コントロールクラスから呼び出すようにしました。
>>この部分ですが、上記だと2回SQLが動くことになりますよね。
>>次のようにされてみてはどうでしょう?
>>MySQLということで。
>>$sql = "SELECT SQL_CALC_FOUND_ROWS "
>>           . "* "
>>     . "FROM "
>>     	   . "TABLE_NAME "
>>     . "WHERE "
>>     	   . "A = B "
>>     . "LIMIT 0, 20 "
>>$result = $this->db->query($sql);
>>$count  = $this->db->query("SELECT FOUND_ROWS() as count");
>>として、
>>$count = $total->row();
>>var_dump($count->count);
>>とすればトータル件数が取り出せますね。
>>3000件程度でベンチとりました。
>>こちらのほうが、0.0001〜0.0003早いようです(笑)
>>件数が多くなればこちらのほうがいいのでしょうかね。
>>少なくともMyISAMならcount(*)は特殊な取り出ししますが、InnoDBなどの場合は
>>たぶんもっと差が出るのではないでしょうか?
>>_______________________________________________
>>Codeigniter-users mailing list
>>Codei****@lists*****
>>http://lists.sourceforge.jp/mailman/listinfo/codeigniter-users
>
> _______________________________________________
> Codeigniter-users mailing list
> Codei****@lists*****
> http://lists.sourceforge.jp/mailman/listinfo/codeigniter-users
>


---
木村




Codeigniter-users メーリングリストの案内
Back to archive index