ホーム » ビジネスブログ » Zen Cart(オンラインショップ構築) »

Zen Cart 高速化:ハイエンド版「かんたんカテゴリ管理」画面を商品数10万でも快適に

2015年9月16日

Zen Cart 高速化:ハイエンド版「かんたんカテゴリ管理」画面を商品数10万でも快適に

投稿者 金田

Zen Cartハイエンド版の「かんたんカテゴリ管理」機能が遅い!

Zen Cartハイエンド版 で、商品を10万件データベースに登録したときのパフォーマンスをチェックしてみたところ、「かんたんカテゴリ管理」のトップ階層を表示させるのに時間がかかっていることが判明した。
そのため、遅くなっている原因を追求し、時間が掛かっている部分を改良(チューニング)することで速度向上を行った。

「かんたんカテゴリ管理」とは、Zen Cartハイエンド版で提供されている管理者向けのカテゴリ・商品管理のアドオン・モジュールである。かんたんカテゴリ管理を使うと、カテゴリの新規登録や階層の操作、カテゴリへの商品の追加などを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万あるような場合でも問題ないパフォーマンスが出るようになったことがわかる。

投稿者 金田 : 2015年9月16日 11:52

カテゴリー: Zen Cart(オンラインショップ構築)

タグ: チューニング , デバッグ , ECサイト , 高速化 , Zen Cart , Zen Cartカスタマイズ , Zen Cart高速化


Movable Type用高機能メールフォーム生成プラグイン A-Formの詳細へ
Movable Type用会員限定サイトプラグイン A-Memberの詳細へ
Movable Type用予約サイト構築プラグイン A-Reserveの詳細へ
ARK-Web×CSR(企業の社会的責任)

アークウェブの本

Zen Cartによるオンラインショップ構築・運用テクニック―オープンソース徹底活用

Zen Cartによるオンラインショップ構築・運用テクニック―オープンソース徹底活用

内容充実のZen Cart公式本(v1.3対応)がついに発表です。アークウェブのスタッフをはじめZen-Cart.JPの中心メンバーが共著で執筆しました。続きを読む

Movable Type プロフェッショナル・スタイル

Movable Type プロフェッショナル・スタイル

ビジネスサイト構築におけるCMSとしてのMTの活用方法について、豪華執筆陣による実践的MT本です。八木が共著で執筆しました。続きを読む

Web屋の本

Web屋の本

Web 2.0時代の企業サイトの構築・運用などの戦略を考える「Web屋の本」 (技術評論社)を、中野・安藤が執筆しました。続きを読む

新着はてブ

Loading

アーカイブ

応援しています

  • キッズ・セーバー
  • ソロモン・リリーフ ─ソロモン諸島を応援する有志による、震災復興支援プロジェクト─

    (終了しました)

RSS配信

 

サービスおよびソリューション一覧


最新情報・投稿をチェック


このページのトップに戻る

Photo by A is for Angie

Powered by Movable Type Pro 6.0.1