Kimura A
a.kim****@live*****
2013年 9月 20日 (金) 19:53:58 JST
木村です。 先ほど、手違いで少し古いファイルをペーストして送ってしまいました。すみません。 Insertシェルについては以下の内容でテストよろしくお願いしますo(>_<)o <?php App::uses('AppShell', 'Console/Command'); /** * mroonga「WHERE IN 多数」クエリのテスト用データ生成シェル * * @property Model $Model */ class InsertShell extends AppShell { /** * メイン処理 * * @param Model $Model * @return void */ public function main() { $limit = 100; // 1度にいくつのレコードをINSERTするか $minutes = 5; // 実行を許可する最大分数。cronによる動作時の重複回避用 $headRoomSec = 10; // 実行許可分間のうち処理の重複回避のために何秒の余裕を残すか // モデルを準備して接続先をtestデータベースに切り替え $this->Model = ClassRegistry::init('Product'); $this->Model->setDataSource('webTest'); // ロックファイルがある場合 if (file_exists(TMP . 'mroonga_errored')) { if ($this->Model->find('first', array('fields' => array('id')))) { // productsテーブルが空でない場合:エラー再現条件をすでに満たしているとみなして終了 CakeLog::debug("mroonga_erroredファイルが存在するためINSERT処理を回避します"); return; } @unlink(TMP . 'mroonga_errored'); } // 実処理 CakeLog::debug("{$limit}件単位の一括INSERT処理({$minutes}分間)を開始します"); $startTS = time(); // 処理開始TS $timeLimitTS = $startTS + (60 * $minutes) - $headRoomSec; // 想定上のタイムリミットTS:$headRoomSec秒の余裕を確保 $loopSecMax = 0; // 1回のループに要した最大秒数を保持 for ($i = 0; $i < 10000; $i++) { if ($i) { // 初回ループ以外は1秒のインターバルを挟む sleep(1); } // ループ処理開始時刻を保持 $loopStart = time(); // 一括INSERT実行 if (!$this->insert($limit)) { // エラー時停止 return; } // 一括INSERTの所要秒数を算出 $loopSec = time() - $loopStart; // 一括INSERTの最大所要秒数を特定 $loopSecMax = max(array($loopSecMax, $loopSec)); // 一括INSERTの最大所要秒数を基準に、トータル処理時間が次のループで所定の秒数を超過しないかチェック:後続のSelectシェル処理との重複回避 $loopEndTS = time(); if ($loopSecMax > ($timeLimitTS - $loopEndTS)) { // 超過の可能性がある場合はログを出力して処理を停止 $loopCount = $i + 1; $totalSec = $loopEndTS - $startTS; $maxId = $this->getMaxId(); $dbNameData = $this->Model->query('SELECT database() as `db`;', false); $dbName = $dbNameData[0][0]['db']; CakeLog::debug("{$minutes}分間のタイムリミットが近いため処理を終了します。DB名:{$dbName}/最大products.id:{$maxId}/トータル動作秒数:{$totalSec}/ループ回数:{$loopCount}/ループ最大所要秒数:{$loopSecMax}/ヘッドルーム秒数:{$headRoomSec}"); break; } } } /* * 現時点での最大products.id値を取得 */ public function getMaxId() { $record = $this->Model->find('first', array( 'fields' => array('id'), 'order' => 'Product.id DESC' )); return empty($record['Product']['id']) ? 0 : $record['Product']['id']; } /* * 一括INSERT実行 */ public function insert($limit) { // クエリの構成 $sql = "INSERT INTO test.products (id, code, description, vendor_id, tag_pool) VALUES "; $id = $this->getMaxId(); $vendorId = 1; for ($i = 0; $i < $limit; $i++) { // 個別レコードを準備 $id++; $sqlChild = "(null"; foreach (array('code', 'description', 'vendor_id', 'tag_pool') as $field) { switch ($field) { case 'code': $sqlChild .= ", 'code{$id}'"; break; case 'description': case 'tag_pool': $sqlChild .= ", '" . $this->getText(1000) . "'"; break; case 'vendor_id': $sqlChild .= ", 1"; break; case 'title': $sqlChild .= ", 'タイトル{$id}'"; } } $sqlChild .= ")"; if ($i) { $sql .= ', '; } $sql .= $sqlChild; } $sql .= ";"; // 一括INSERT実行 $this->Model->query($sql); return true; } /* * TEXTカラム用のランダム文字列を構成 */ public function getText($len = 100) { // 5文字程度で半角スペース区切りになった文字列データを生成するためスペースを混入させておく $sCharList = "abcde fghij klmno pqrst uvwxy zABCD EFGHI JKLMN OPQRS TUVWX YZ012 34567 89_-, ."; mt_srand(); $sRes = ''; for($i = 0; $i < $len; $i++) { $sRes .= $sCharList{mt_rand(0, strlen($sCharList) - 1)}; } return $sRes; } } ?>