EC-CUBEのカスタマイズ、ネットショップ制作メモ

主にEC-CUBEを利用したネットショップの制作、カスタマイズや独自機能の開発について

EC-CUBEをチューニング - MySQL:準備編

先日、EC-CUBE高速化カスタマイズサービスEC-CUBEのパートナー企業からリリースされました。
クロスキューブにもEC-CUBEのパフォーマンスチューニングのお問い合わせはチョコチョコ来ます。*1
やっぱりEC-CUBEのパフォーマンスで苦労されている方が多いんでしょうね。

EC-CUBEは商品点数が多いと遅いと言われますが、そこまで遅くありません。
ただ、ある特定の条件を満たすと、激重になります。
その条件とは、

  • データベースにMySQL*2を使う。
  • 規格が多い。
  • カテゴリが多い。

です。
特に規格を「規格1」、「規格2」両方大量に設定した場合は酷い事になります。
これは設計上どうしようも無い部分なので、EC-CUBE 2.5.0で改善されるのを祈るばかりです。

そこで、この遅い条件を満たした時、どこまでチューニング出来るか試してみる事にしました。

VMにCentOS5とEC-CUBE 2.4.4をインストール

まず環境を構築します。
VMCentOSをインストールして、EC-CUBEをインストールします。
今回構築したのは以下の環境です。*3

商品データを生成

次に、EC-CUBEtracから商品データの生成スクリプトをダウンロードします。
次に自分の環境に合わせて、/data/install.phpを見ながらデータ生成スクリプトを編集します。

29行目:require_once("DB.php");
インストールしたEC-CUBEの /data/module/DB.php へのフルパスに変えます。
35行目:define("DB_TYPE", "pgsql");
define("DB_TYPE", "mysql"); に変更
39行目:define("DB_PORT", "5432");
データベースへの接続ポートです。MySQLのデフォルトは3306なので、define("DB_PORT", "3306"); に変えます。install.phpと一緒でOK
41行目:define("DB_NAME", "eccube_db");
EC-CUBEをインストールしたデータベース名です。install.phpと一緒でOK
43行目:define("DB_USER", "eccube_db_user");
EC-CUBEをインストールしたデータベースのユーザ名です。install.phpと一緒でOK
45行目:define("DB_PASSWORD", "password");
EC-CUBEをインストールしたデータベースユーザのパスワードです。install.phpと一緒でOK
53行目:define("TOP_CATEGORIES_VOLUME", 5);
トップレベルのカテゴリ生成数
56行目:define("MIDDLE_CATEGORIES_VOLUME", 2);
第2レベルのカテゴリ生成数
59行目:define("SMALL_CATEGORIES_VOLUME", 3);
第3レベルのカテゴリ生成数
62行目:define("CLASSCATEGORY1_VOLUME", 1);
規格1の規格生成数※ここを増やし過ぎると重過ぎて動かなくなります。3でも重いです。
65行目:define("CLASSCATEGORY2_VOLUME", 2);
規格2の規格生成数※ここを増やし過ぎると重過ぎて動かなくなります。3でも重いです。
68行目:define("PRODUCTS_VOLUME", 100);
商品データの生成数※ここを増やし過ぎると重過ぎて動かなくなります。8,000くらいがちょうど良いかも。

また、この商品データ生成スクリプトPostgreSQL用に書かれているので、以下のSQLを修正します。
290行目付近:

$sqlval['rank'] = "~(SELECT CASE
                                WHEN max(rank) + 1 IS NULL THEN 1
                                ELSE max(rank) + 1
                            END
                        FROM dtb_class
                        WHERE del_flg = 0),";

$sqlval['rank'] = "~(SELECT CASE
                                WHEN max(T2.rank) + 1 IS NULL THEN 1
                                ELSE max(T2.rank) + 1
                            END
                        FROM dtb_class AS T2
                        WHERE T2.del_flg = 0),";

に変更。

318行目付近:

$sqlval['rank'] = sprintf("~(SELECT CASE
                                        WHEN max(rank) + 1 IS NULL THEN 1
                                        ELSE max(rank) + 1
                                    END
                                FROM dtb_classcategory
                                WHERE del_flg = 0
                                AND class_id = %d),", $class_id);

$sqlval['rank'] = sprintf("~(SELECT CASE
                                        WHEN max(T2.rank) + 1 IS NULL THEN 1
                                        ELSE max(T2.rank) + 1
                                    END
                                FROM dtb_classcategory AS T2
                                WHERE T2.del_flg = 0
                                AND T2.class_id = %d),", $class_id);

に変更。

修正したスクリプトを適当なディレクトリに置いて、以下のコマンドをコンソールから実行します。

$ php -f CreateEcCubeData.php

すると商品情報の生成が始まります。処理が終わるまでしばらく待ちましょう。*4

スクリプトの処理が終わったら、EC-CUBEの管理画面にアクセスして、どれでも良いのでひとつ商品情報を更新します。その際にカテゴリデータの更新処理が走るので、EC-CUBEのショップ画面に表示されるカテゴリナビに登録した商品が表示される様になります。
あと、管理画面の [システム設定] > [パラメータ設定]で、ADMIN_MODEを1にしておきましょう。EC-CUBEのショップ画面に処理時間が表示される様になります。

EC-CUBEのショップ画面を表示してみる。

上記の作業が終わったら、EC-CUBEのショップ画面を表示してみましょう。
トップ画面、全商品一覧画面*5を見てみましょう。どれくらい表示に時間がかかりましたか?
ちなみに僕の環境では、

トップカテゴリ 生成数 15
第2カテゴリ 生成数 5
第3カテゴリ 生成数 3
規格1 生成数 3
規格2 生成数 2
商品点数 8,000

で生成して、

ショップトップ画面 オススメ商品有:839秒
オススメ商品無:0秒
全商品一覧 917秒

でした。*6
このスクリプトは全商品を全カテゴリに登録してしまうので*7、この程度の数でもこんな結果です。いや〜遅いですね!

さて、どこから手をつけましょうか。
続きはまた次回書きますので、乞うご期待!

*1:大体がDBをPostgreSQLに変えたら解決しますが...

*2:特に4.1系

*3:それぞれのインストール方法は先生に聞いて下さい。多分いっぱい出て来ます。

*4:PHPのnoticeエラーが表示されたりしますが、気にしなくて良いです。

*5:/products/list.phpにアクセスすれば表示されます。

*6:CentOS上のFirefoxからアクセスしたので、ネットワークの遅延はほぼ無いです。1

*7:dtb_prducts_categoryに250万行くらいレコードが生成されてました...