ブログ

ZenCartのスケーラビリティ向上

2007年04月26日 │ 谷口

谷口です。

弊社ではzencartをカスタマイズして、システムの開発を行なっております。
私が携わっているシステムでは、登録商品数の増加やカスタマイズ部分の肥大化に伴って、
レスポンスが非常に遅くなっていました。

スピードアップを図った際に行なった作業や、
使用したzencartのツールや機能の紹介をします。

スピードアップで行なった作業

  • クエリキャッシュの利用
  • 不要なモジュールの削除
  • インデックスの作成
  • 一覧表示用テーブルの作成

zencartのツール

  • parse time計測

 application_top.phpにある以下の定数をtrueにすると有効になります。
デフォルトでは、フッター部分にPHPの実行時間やSQLクエリの数、総実行時間などが表示されます。

define(‘DISPLAY_PAGE_PARSE_TIME’, ‘true’);

  • query time計測

 query_factoryオブジェクトのqueryTime()メソッドを用います。
このメソッドは、呼ばれたときまでのSQLクエリの総実行時間を返しますので、
個々に見る場合は、Wrapするなどの対処をします。

キャッシュ

 zencartのquery_factoryオブジェクトには、独自にSQL文の結果をキャッシュできる仕組みがあります。
キャッシュ情報を保持する場所をファイル・メモリ・データベースのいずれかで選択可能です。

//query_factoryオブジェクト生成
$db = new queryFactory();
$zc_cache = new cache;

$result = $db->Execute($sql, $limit, true, $time);

という具合に、Executeメソッドの第3引数をtrueにすることで、
$time(秒)だけキャッシュが有効になります。

不要な処理の削除

 カスタマイズの要件に依存しますので、詳細は割愛させていただきます。
要・不要とは別にして、「価格情報取得」や「前の商品・次の商品」は、
独自で作った方が良いかもしれません。以下で簡単に理由を述べます。

  • 価格情報取得

 商品価格を取得する関数の中で、SQLクエリが何回か実行されるわけですが、
ほとんどのクエリのfrom以降が全く同じだからです。

  • 前の商品・次の商品

 表示している商品と同じカテゴリの商品を全て取得し、
その中から表示している商品の前後を抽出するような手順となっています。
この部分はデータベースに頑張ってもらった方が、何かと都合が良さそうです。

データベース関連

  • インデックス作成

 基本ですが、結合に用いるカラム・条件によく使われるカラム・order by句に用いるカラムなどにインデックスを作成します。

  • 一覧表示テーブル作成

 カスタマイズ部分の肥大化が主たる原因ですが、テーブル結合すると非常に遅くなることが目立っていました。
そのため、あらかじめ結合した結果で構成されるテーブルを用意し、
そのテーブルに対してクエリを発行することで、結合によって生じていた遅さを緩和しました。
mysql4系だったため、viewを使えなかったこともあったので、苦肉の策的な措置でしたが、
かなり効果はありました。
ちなみに、テーブル更新はcreateし直してます。同じテーブルを2つ用意して、
更新時に切り替えるようにすることで、継続的に存在しているようにしました。

まとめ

 割と基本的なことしかしてませんが、今回紹介した手法はどれも劇的に表示速度が向上しました。特に効果の高かったページでは、数倍~10数倍くらいの速度向上が見られるものもありました。また、zencartが大規模商品展開に向いていない部分があることを見つけ出せたのは、収穫だったと思います。他にも効果的な手法があったら、随時掲載したいと思います。