2015年9月16日
Zen Cart 高速化:ハイエンド版「かんたんカテゴリ管理」画面を商品数10万でも快適に
Zen Cartハイエンド版の「かんたんカテゴリ管理」機能が遅い!
Zen Cartハイエンド版 で、商品を10万件データベースに登録したときのパフォーマンスをチェックしてみたところ、「かんたんカテゴリ管理」のトップ階層を表示させるのに時間がかかっていることが判明した。
そのため、遅くなっている原因を追求し、時間が掛かっている部分を改良(チューニング)することで速度向上を行った。
「かんたんカテゴリ管理」とは、Zen Cartハイエンド版で提供されている管理者向けのカテゴリ・商品管理のアドオン・モジュールである。かんたんカテゴリ管理を使うと、カテゴリの新規登録や階層の操作、カテゴリへの商品の追加などをZen Cartよりわかりやすいインターフェイスで行うことができる。
状況を確認してみる
以下に10回あたり(httpサーバ負荷なし)の調査結果を示す。
◆Zen Cartハイエンド かんたんカテゴリ管理 01 42.23 02 42.72 03 42.25 04 42.02 05 38.25 06 39.34 07 40.88 08 42.17 09 36.65 10 42.59 -------- 平均40.91
平均で40.91秒かかっているのが分かる。連続して同じページを表示させているが、DBのキャッシュの効果も出ていないように見られる。
なお比較として、ハイエンド版ではない通常のZen Cartの管理画面「カテゴリ・商品の管理」についても計測したので付記しておく。
◆Zen Cart カテゴリ・商品の管理 01 43.78 02 43.32 03 43.81 04 43.74 05 43.63 06 39.01 07 43.52 08 40.88 09 36.37 10 43.27 -------- 平均42.11
両方とも時間がかかっているが、ハイエンド版の「かんたんカテゴリ管理」の方がやや応答速度が早い。これは、ハイエンド版「かんたんカテゴリ管理」の方が一度に取得しているパラメータが少ないことなどが理由に考えられる。
原因を調査してみる
URL呼び出しから遅い部分を取り出して調べることにする。
かんたんカテゴリ管理の呼び出しは以下のURLで行われる。
https://www.example.com/zencart/admin/addon_modules_admin.php?module=easy_admin_products/categories
URLから、
addon_modules
の名称が、
easy_admin_products
ということが分かる。つまり、対象のモジュールは以下の階層にある。
インストールdir/includes/addon_modules/easy_admin_products/
このディレクトリの中で表示に時間がかかる部分を調べていく。調査には色々な方法があると思うが、今回はprintfデバッグを行った。
printfデバッグとは、通常のデバッガにあるブレークポイントなどの代わりにprint文などのデバッグ用のコードを直接埋め込んでいく最も原始的なデバッグ方法の1つである。パフォーマンスの悪い部分を探すため、print文のほかにもPHPのデフォルト関数であるmicrotime()関数を使って実行時間をチェックしていく。
しばらく試行錯誤を繰り返すと、上記階層のinclude/配下にある
easy_admin_products_category_model.php
というファイル中の
convert_categories_result()
という関数に実行時間が掛かっていることが分かった。さらに対象を絞っていくと、
$categories_values->fields['is_link']
= (zen_get_products_to_categories($categories_id, true, 'products_active') == 'true');
という呼び出しに40秒近く掛かっていることが分かった。前述の統計からすると、41秒の負荷のうちのほとんどがこの1行に集中していることになる。
この行は何をしてるかというと、最終的に$categories_values->fields['is_link']
に真偽値が入るのだが、これの判定にzen_get_products_to_categories()
という関数の呼び出しを行っていることが分かる。
zen_get_products_to_categories()
が定義されている行を調べると、
インストールDir/admin/includes/functions/general.php
にその記述がある。ソースコードを解析していくと、$category_id
以下(選択されているカテゴリ以下)の全ての商品IDを抽出し、親カテゴリが2つ以上あるものを探して真偽値を返している。
つまりこれはリンク商品を探す関数である。Zen Cartでは、2つ以上の親カテゴリに属する商品はリンク商品として扱われる。
今回の場合、商品数が10万レコード存在するため、商品IDのチェックもトップカテゴリでは10万回行われる。いくら高速なMySQLの呼び出しであっても、10万回の問い合わせにはそれなりの時間が掛かる。この部分がボトルネックであることはほぼ確実であるため、この関数の書き換えを行なう。
なお、このモジュールで呼び出されているSQL問い合わせの数は実に100,336回にも及んでいた。
実装してみる
試行錯誤の末、10万回超の問い合わせを180回程度にまとめることができた。リンク商品のIDを今まで1つずつ10万回行っていた点を改良し、1つのSQL問い合わせでリンク商品の一覧を取得するようにした。
まず、child_categories()
というメソッドを新たに作り、自分自身を含む下層カテゴリを全て洗い出す。この関数では効率化のために再帰が使われている。
また、母集合として、カテゴリと商品の関連テーブルを商品テーブルを使用し、JOINしておく。複数のカテゴリに含まれる商品は同じ商品IDが複数回現れるはずである。
母集合をIN()句を使って調べようとしているカテゴリか、その子孫カテゴリに属するものに絞る。
そして商品IDをgroup by句とcount()文を使って出現回数を調べる。2回以上出現するものがリンク商品である。
こうしてSQLクエリの呼び出しを減らした結果、以下のようにかなりのパフォーマンスが得られた。
100,336クエリを発行している(商品数+カテゴリ数+α?)。 ↓ 182クエリに削減(内包カテゴリを再帰で取得(複数クエリ)、リンク商品の有無を1クエリで問い合わせ)
◆削減後のかんたんカテゴリ管理 01 1.23 02 1.02 03 1.30 04 1.03 05 1.01 06 1.00 07 1.15 08 0.96 09 1.04 10 1.00 ------ 平均1.07
ネックとなっていた40秒かかるリンク商品検索部分が高速化されたため、商品数が10万あるような場合でも問題ないパフォーマンスが出るようになったことがわかる。
カテゴリー: Zen Cart(オンラインショップ構築)
タグ: チューニング , デバッグ , ECサイト , 高速化 , Zen Cart , Zen Cartカスタマイズ , Zen Cart高速化
« 前の記事:Movable Type Tips:MT4→MT6バージョンアップはブログ構成の再編成に注意!
» 次の記事:アークウェブ、Movable Type/MTクラウド用プラグインの新版「A-Form(フォーム作成)」「A-Member(会員制サイト構築)」「A-Reserve(予約制サイト構築)」の新版3.8.3をリリース
アークウェブの本
Zen Cartによるオンラインショップ構築・運用テクニック―オープンソース徹底活用
内容充実のZen Cart公式本(v1.3対応)がついに発表です。アークウェブのスタッフをはじめZen-Cart.JPの中心メンバーが共著で執筆しました。続きを読む
新着はてブ
カテゴリー
- Shopify(ショピファイ)オンラインショップ構築
- NGO・NPO向け情報
- スマートフォン
- だれもが使えるウェブコンクール
- mixiアプリ
- OpenSocial (システム開発)
- アークウェブのCSR
- A-Form, A-Member, A-Reserve(MTプラグイン)
- Ruby on Rails(システム開発)
- necoったー
- Miqqle
- WebSig24/7
- ecoったー
- ビッグイシュー(The Big Issue)
- CSR(企業の社会的責任)
- マッシュアップ
- RIA (システム開発)
- セキュリティ(システム開発)
- 唐松(アクセス解析)
- Ajax (システム開発)
- テスト(システム開発)
- データベース
- PukiWiki
- Web 2.0
- SEO・サーチエンジン最適化
- XP・アジャイル(システム開発)
- Web・ITニュースクリップ
- Webアクセシビリティ
- Webデザイン
- SEM・サーチエンジン広告
- Webユーザビリティ
- CMS・MovableType
- Zen Cart(オンラインショップ構築)
- Snippy(SNS・ソーシャルブックマーク)
- アークウェブ
- オープンソース
- CMS(コンテンツマネジメント・システム)
- Webマーケティング
- AMP
- SNS