Hatena::ブログ(Diary)

130単位

2011-03-29

CakePHP 日付別パーティショニングするビヘイビア

MySQL 日付別パーティショニングの運用 - 130単位

前回MySQLのパーティショニングを簡単にまとめてみました。実験はCakePHPアプリでしていて、ついでにつくったビヘイビアを晒してみます。GitHubにもあげてます。

GitHub - deeeki/cakephp-partitionable: Behavior for CakePHP supports MySQL partitioning by date.

ビヘイビア

app/models/behaviors/以下にdate_partitionable.phpとして保存します。中身はSQLをつくって実行しているだけの単純なものです。

<?php
class DatePartitionableBehavior extends ModelBehavior {
    public function createPartition(&$Model, $field, $date) {
        $ts = strtotime($date);
        if ($ts === false) { return false; }

        $partition_name = $this->_getPartitionName($ts);
        $partition_date = $this->_getPartitionDate($ts);

        $sql = "ALTER TABLE {$Model->table} PARTITION BY RANGE (TO_DAYS({$field})) ";
        $sql .= "(PARTITION {$partition_name} VALUES LESS THAN (TO_DAYS('{$partition_date}')) COMMENT = '{$partition_date}')";

        return $Model->query($sql);
    }

    public function removePartition(&$Model) {
        $sql = "ALTER TABLE {$Model->table} REMOVE PARTITIONING";

        return $Model->query($sql);
    }

    public function addPartition(&$Model, $date) {
        $ts = strtotime($date);
        if ($ts === false) { return false; }

        $partition_name = $this->_getPartitionName($ts);
        $partition_date = $this->_getPartitionDate($ts);

        $sql = "ALTER TABLE {$Model->table} ADD PARTITION ";
        $sql .= "(PARTITION {$partition_name} VALUES LESS THAN (TO_DAYS('{$partition_date}')) COMMENT = '{$partition_date}')";

        return $Model->query($sql);
    }

    public function dropPartition(&$Model, $date) {
        $ts = strtotime($date);
        if ($ts === false) { return false; }

        $partition_name = $this->_getPartitionName($ts);

        $sql = "ALTER TABLE {$Model->table} DROP PARTITION {$partition_name}";

        return $Model->query($sql);
    }

    private function _getPartitionName($ts) {
        return 'p' . date('Ymd', $ts);
    }

    private function _getPartitionDate($ts) {
        return date('Y-m-d', $ts + 86400) . ' 00:00:00';
    }
}

Cakeシェル

Cakeシェルのサンプルです。app/vendors/shells/以下にpartition.phpとして保存します。usesプロパティの先頭要素のモデルがパーティショニングの対象になります。main()以外のメソッドをつくることで、Cakeタスクの代わりになります。引数でモデルを指定してもよかったのですが、面倒なのでやめました。

<?php
class PartitionShell extends Shell {
    public $uses = array('GameHistory'); //input partitionable target model name on first.
    public $tasks = array();

    public function startup() {
        $this->{$this->modelClass}->Behaviors->attach('DatePartitionable');
    }

    public function create() {
        $count = (isset($this->args[0])) ? intval($this->args[0]) : 1;

        $this->{$this->modelClass}->createPartition('created', date('Ymd'));
        for ($i = 1; $i < $count; $i++) {
            $this->{$this->modelClass}->addPartition(date('Ymd', strtotime('+' . $i . ' days')));
        }
    }

    public function remove() {
        $this->{$this->modelClass}->removePartition();
    }

    public function add() {
        if (!isset($this->args[0])) {
            $this->err("[ERROR] require date parameter. ex: 'add 20110101'");
            return;
        }
        $this->{$this->modelClass}->addPartition($this->args[0]);
    }

    public function drop() {
        if (!isset($this->args[0])) {
            $this->err("[ERROR] require date parameter. ex: 'drop 20110101'");
            return;
        }
        $this->{$this->modelClass}->dropPartition($this->args[0]);
    }
}

Cakeシェル実行例

cake/console/cake partition create
#-> ALTER TABLE game_histories PARTITION BY RANGE (TO_DAYS(created)) (PARTITION p20110329 VALUES LESS THAN (TO_DAYS('2011-03-30 00:00:00')) COMMENT = '2011-03-30 00:00:00')
cake/console/cake partition add 20110330
#-> ALTER TABLE game_histories ADD PARTITION (PARTITION p20110330 VALUES LESS THAN (TO_DAYS('2011-03-31 00:00:00')) COMMENT = '2011-03-31 00:00:00')
cake/console/cake partition drop 20110330
#-> ALTER TABLE game_histories DROP PARTITION p20110330
cake/console/cake partition remove
#-> ALTER TABLE game_histories REMOVE PARTITIONING

直打ちで試してみて問題なさそうであれば、cronジョブに登録して自動化するといいんじゃないかと思います。不具合などありましたらご報告いたけますと助かります!


4798027456
Pocket詳解 CakePHP辞典

4774142948
エキスパートのためのMySQL[運用+管理]トラブルシューティングガイド

関連記事

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/deeeki/20110329/cakephp_partitioning_behavior
Connection: close