日: 2008年12月2日

【EC-CUBE】売り上げ集計をバッチモードにして動作を軽減(再びCRON)

EC-CUBEの売り上げ集計は2つのモードが選択でき、デフォルトは、リアルタイム集計。処理が長くなると、タイムアウトしてしまったり、ダウンしてしまう。

  1. リアルタイム・・・「月度で集計する」や「期間で集計する」ボタンが押されたときにその場で集計→集計データ格納→集計データ取得→表示、と行う方法。
  2. バッチモード・・・あらかじめ売上データを集計しておき、「月度で集計する」や「期間で集計する」ボタンが押されたときには、すでに集計して格納済みのデータを取得→表示、と行う方法。

その1)管理モードの変更

管理画面→システム管理→パラメータ管理で、
DAILY_BATCH_MODEを[false]から[true]に変更。

その2)/data/script/execute_batch_daily.phpを作成。

/**
* デイリーバッチ起動スクリプト
*/

require_once( dirname(__FILE__) . “/../install.php” );
define( “CLASS_PATH”, DATA_PATH . ‘class/’ );
define( “CLASS_EX_PATH”, DATA_PATH . ‘class_extends/’ );
define( “CACHE_PATH”, DATA_PATH . ‘cache/’ );

require_once(CLASS_EX_PATH . “util_extends/GC_Utils_Ex.php”);
require_once(CLASS_EX_PATH . “util_extends/SC_Utils_Ex.php”);
require_once(CLASS_EX_PATH . “db_extends/SC_DB_MasterData_Ex.php”);
require_once(CLASS_EX_PATH . “db_extends/SC_DB_DBFactory_Ex.php”);
require_once(CLASS_PATH . “SC_DbConn.php”);
require_once(CLASS_PATH . “SC_Query.php”);
require_once(CLASS_PATH . “SC_SelectSql.php”);

require_once(CLASS_EX_PATH . ‘batch_extends/SC_Batch_Daily_Ex.php’);
require_once(CLASS_EX_PATH . “SC_Initial_Ex.php”);
// アプリケーション初期化処理
$objInit = new SC_Initial_Ex();
$objInit->init();

$usage = <<

php -f execute_batch_daily.php start term
集計期間を指定して売上集計をします。

 start 集計開始日。何日前の売上から集計するか。1 から 365以内で指定。
 term 集計対象期間。何日分の売上を集計するか。1 から 365以内で指定。

例:昨日の売上を集計します。
php -f execute_batch_daily.php 1 1

USAGE;

if ( $argc != 3 ) {
echo ( $usage );
exit(1);
}

$start = $argv[1];
$term = $argv[2];
if ( !is_numeric( $start ) || !is_numeric( $term ) ) {
echo ( $usage );
exit(1);
}

$start = intval( $start );
$term = intval( $term );

if ( $start < 1 || $start > 365 || $term < 1 || $term > 365 ) {
echo ( $usage );
exit(1);
}

if ( $term > $start ) {
echo ( $usage );
exit(1);
}

$objBatch = new SC_Batch_Daily_EX();
$objBatch->lfStartDailyTotal( $term, $start, true );
?>

その3)/data/class/batch/SC_Batch_Daily.phpを修正。

L92,93(ver.2.3.2の場合)

// 削除された受注データの受注詳細情報の削除
$objQuery = new SC_Query();
//$where = “order_id IN (SELECT order_id FROM dtb_order WHERE del_flg = 1)”; ←コメントアウト
//$objQuery->delete(“dtb_order_detail”, $where); ←コメントアウト

// 最後に更新された日付を取得

// 最後に更新された日付を取得

L102(ver.2.3.2の場合)

// 最後のバッチ実行からLOAD_BATCH_PASS秒経過していないと実行しない。
if($pass < LOAD_BATCH_PASS) {
//GC_Utils_Ex::gfPrintLog(“LAST BATCH ” . $arrRet[0][‘create_date’] . ” > ” . $batch_pass . ” -> EXIT BATCH $batch_date”); ←コメントアウト
$batch_next = date( “Y-m-d H:i:s”, strtotime($batch_last) + LOAD_BATCH_PASS ); ←追加
GC_Utils_Ex::gfPrintLog(“LAST BATCH ” . $batch_last . ” NEXT BATCH AFTER $batch_next -> EXIT BATCH”); ←追加

return;
}

L107(ver.2.3.2の場合)

// 集計
//for ($i = $start; $i < $term; $i++) { ←コメントアウト
for ($i = $start, $k = 0; $k < $term; $i–, $k++ ) { ←追加
// 基本時間から$i日分さかのぼる
$tmp_time = $now_time – ($i * 24 * 3600);

L154(ver.2.3.2の場合)

GC_Utils_Ex::gfPrintLog(“LOADING BATCH $batch_date”);
$this->lfBatOrderDaily($tmp_time);
$this->lfBatOrderDailyHour($tmp_time);
$this->lfBatOrderAge($tmp_time);
// タイムアウトを防ぐ ←追加
SC_Utils_Ex::sfFlush(); ←追加

}
}

※そもそも集計時にSQLエラーになるところがあるので、先に
http://www.bton.net46.net/?p=724
の修正を行っておくこと。

その4)CRONの設定

0 2 * * * /usr/local/bin/php -f /path/to/eccube/data/script/execute_batch_daily.php 1 1 2>&1 > /dev/null

参考サイト:http://d.hatena.ne.jp/yuhei_kagaya/20081019

【EC-CUBE】集計ページが正しく表示されない・・・対応策の備忘録

集計表示でタイムアウト・・・デフォルトではリアルタイム集計をしているので、動作が重くサーバに負荷も掛かってしまう。

思い切ってバッチ処理で夜中に前日までの売り上げを集計しておくことにする。これで、集計を見るときにはサックサク動くはず。

と思ったら、いくつかバグがあり、MYSQLを使っていると、バグを踏んでるいくつかの集計は表示されない。エラーでまくり、なんだこりゃ。全体的に、MYSQL関係でなんだかんだとエラーが出るんだね。

てことで、バッチ処理にする手前で、虫退治に出かけることになる。。。

表示できなかったのは、mySQLを使用した際、ポスグレでは利用できるtrunc関数をmySQL用にtruncate関数へ変換する処理が上手く機能していないため。

そこで、シンタックスエラーになっていたSQL構文を修正し、動作不良を修正。その後、MYSQL用にtrunc→truncate変換をしているsfChangeMySQLが2重に掛かっている(と思われる)部分をコメントアウト。コレで何とかサクサク動作を手に入れた;

その1)シンタックスエラーの修正。

/data/class/batch/SC_Batch_Daily.php (L189、L271:ver.2.3.2の場合)

/data/class/pages/admin/total/LC_Page_Admin_Total.php (L641、L709:ver.2.3.2の場合)

上記2つのファイルの(AVG(total))→(AVG(total),0)へ変更
この時点で、エラーの出ていた職業別集計と会員別集計のうち職業別集計は表示されるようになる。

その2)trunc→truncate変換をしているsfChangeMySQLの2重適用部分をコメントアウト。

/data/class/SC_Query.php (L94:ver.2.3.2の場合)

この中の、$sqlse = $dbFactory->sfChangeMySQL($sqlse); 1行をコメントアウト(または削除)

※/data/class/SC_Query.phpの$sqlseというのが、なんに使われているのか分からなかったが、ここでは、sfChangeMySQLの処理を行っているだけで、同じ処理がSC_DbConnでも順に行っていることから不要かと判断する。

これで動作はエラーがなくなった。
あとはバッチ処理で夜中にcronを動かすのみ。だ~~~~~。