2009年10月31日

EC-Cube&MySQL 5.0以降を利用しているときのおまじない

MySQL 5.0以降を利用しているならば、Viewが利用できるようになっているので、ぜひ、Viewを使ったほうがいいでしょう。

というのは、「規格」数が増えてきた場合や、「規格1」×「規格2」で発生するSKU(在庫管理単位)が多くなると、管理画面でタイムアウトを起こしてしまうほど、時間がかかるという問題にぶつかりました。

このような事例が、EC-Cubeの問題点で、ネット上でもちらほら見かけられますが、ハッキリ言えば、MySQLを止めて、PostgreSQLに移行するというのも一つの手なんだと思います。ただ、すでに構築しているサイトのDBを変えるというのは結構大変な作業ですし、できればなんとか回避したいと思うわけです。

具体的には、\data\class\db\dbfactory\SC_DB_DBFactory_MYSQL.php の中にある、function viewToSubQuery() を参照します。

ここで書かれている、Viewの置き換えクエリを、単純に create view するだけです。
たとえば、vw_cross_class については、DB上で、
create view view_cross_class as SELECT T1.class_id AS class_id1, T2.class_id AS class_id2, T1.classcategory_id AS classcategory_id1, T2.classcategory_id AS classcategory_id2, T1.name AS name1, T2.name AS name2, T1.rank AS rank1, T2.rank AS rank2 FROM dtb_classcategory AS T1, dtb_classcategory AS T2;
という感じで、view_cross_classというviewを作ってしまいます。(SELECT以下は、viewToSubQuery()に書かれていた内容)
そのうえで、このビューがプログラムのどこで使われているか、というのを個別に直すのは大変なので、
"vw_cross_class" => '(SELECT T1.class_id AS class_id1, T2.class_id AS class_id2, T1.classcategory_id AS classcategory_id1, T2.classcategory_id AS classcategory_id2, T1.name AS name1, T2.name AS name2, T1.rank AS rank1, T2.rank AS rank2 FROM dtb_classcategory AS T1, dtb_classcategory AS T2)'
のところを、
"vw_cross_class" => 'view_cross_class'
としてしまえばいいわけです。

注意しなければならないのは、vw_cross_products_classにもありますが、サブクエリを含んでいる場合です。ビューでは、サブクエリを含んではいけないようです。
"vw_cross_products_class" =>'
                (SELECT T1.class_id1, T1.class_id2, T1.classcategory_id1, T1.classcategory_id2, T2.product_id,
                T1.name1, T1.name2, T2.product_code, T2.stock, T2.price01, T2.price02, T1.rank1, T1.rank2
                FROM (SELECT T1.class_id AS class_id1, T2.class_id AS class_id2, T1.classcategory_id AS classcategory_id1, T2.classcategory_id AS classcategory_id2, T1.name AS name1, T2.name AS name2, T1.rank AS rank1, T2.rank AS rank2
                FROM dtb_classcategory AS T1, dtb_classcategory AS T2
) AS T1 LEFT JOIN dtb_products_class AS T2
                ON T1.classcategory_id1 = T2.classcategory_id1 AND T1.classcategory_id2 = T2.classcategory_id2) '
と書かれていますが、この中のサブクエリ(赤文字部分)を、まずビューにしてしまいます。DB上で、
create view view_cross_products_class_sub as SELECT T1.class_id AS class_id1, T2.class_id AS class_id2, T1.classcategory_id AS classcategory_id1, T2.classcategory_id AS classcategory_id2, T1.name AS name1, T2.name AS name2, T1.rank AS rank1, T2.rank AS rank2
                FROM dtb_classcategory AS T1, dtb_classcategory AS T2;
ということで、上記の赤文字部分は view_cross_products_class_sub になりました。その上で、
create view view_cross_products_class as SELECT T1.class_id1, T1.class_id2, T1.classcategory_id1, T1.classcategory_id2, T2.product_id,
                T1.name1, T1.name2, T2.product_code, T2.stock, T2.price01, T2.price02, T1.rank1, T1.rank2
                FROM view_cross_products_class_sub AS T1 LEFT JOIN dtb_products_class AS T2
                ON T1.classcategory_id1 = T2.classcategory_id1 AND T1.classcategory_id2 = T2.classcategory_id2;
とSQL文を実行することで、view_cross_products_clasが作成できます。もちろん、これができたら、viewToSubQuery()内で、
"vw_cross_products_class" => 'view_cross_products_class'
としてしまうのがいいでしょうね。

根本的な解決策になっていないのでは?というご指摘もごもっともで、速度向上のために(というか、タイムアウト回避のために)ビューを使うのは本末転倒ではないか、という話もわかります。
ですが、サブクエリを都度発行するよりもビューにしたほうが、私の使っているレンタルサーバでは現実的に速くなってタイムアウトしなくなりました。
OSかMySQLの実装問題なんだと思いますけど、ビューが別スレッドで処理されたりして、メモリ割当がスムーズにいっているのかなぁ、とか。

おまじないのような方法なので、推奨はしませんが、もし、EC-Cubeの商品管理画面で商品一覧表示後に、「規格」のボタンをクリックしても、いつまでたってもサーバから返答がない・・・、といったトラブルに見舞われた方、もしかすると、上の方法で解決するかもしれませんよ。

dmatsu2005 at 14:18コメント(2)トラックバック(0) 
EC-Cube 

トラックバックURL

コメント一覧

1. Posted by 悩みました   2010年07月14日 15:45
5 ズバリの内容で大変助かりました。
ありがとうございます
2. Posted by dmatsu2005   2010年07月15日 20:18
> ズバリの内容で大変助かりました。
> ありがとうございます

参考になれば幸いです。
おまじない、なんですが、そこそこ効きますよね!?

コメントする

名前:
URL:
  情報を記憶: 評価:  顔   星
 
 
 
livedoor プロフィール

アロハ

痩せないと死ぬよっていう宣告を受けてしまったので、ダイエットに目覚めたプログラマー(約95kg)

広告

レンタルサーバーなら使えるねっと


Google AdSense
Google検索
訪問者数
  • 今日:
  • 昨日:
  • 累計:

オススメの書籍