river-jdbc試用


river-jdbcMySQLに登録されたデータをElasticsearchに流し込むことができる便利なプラグインである。
ただし、利用時に注意点がある。
対象件数が多い場合にデフォルト設定だと、MySQLに登録された件数とElasticsearchに追加された件数があわないことがある。
その場合は、max_bulk_requestsの値をデフォルトの30から変更してみるとうまくいくかもしれない。
もう1点、インデックスは未作成でも自動的に作成してくれるが、マッピング情報は事前に設定しておいたほうがよい。

"post"というTypeを設定した"posts"という名前のIndexを作成する
curl -XPOST localhost:9200/posts/ -d '
{
  "mapping": {
    "post": {
      "properties": {
        "id": { "type": "integer", "index": "not_analyzed" },
        "title": { "type": "string", "index": "not_analyzed" },
        "body": { "type": "string", "index": "not_analyzed" }
      }
    }
  }
}
'
"sample"データベースの"posts"テーブルからデータを抽出してElasticsearchに流し込む
{
  "type" : "jdbc",
  "jdbc": {
    "url" : "jdbc:mysql://localhost:3306/sample",
    "user" : "root",
    "password" : "",
    "sql" : "select id,title,body from posts",
    "index" : "posts",
    "type" : "post",
    "bulk_size" : 100,
    "max_bulk_requests" : 1 // ここがポイント
  }
}

32万件ほどのデータで試すと、max_bulk_requestsがデフォルトのままだと18万件程度しか登録されなかった。
これを8に変更すると、全件登録することができた。登録時間は10〜20秒程度。
ソースまで確認してないが、とりあえずこれでもれなく登録できた。

[MySQL]Install MySQL5.6

$ cd
$ sudo yum install ncurses-devel cmake bison gcc-c++
$ mkdir src
$ cd src/
$ wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.16.tar.gz
$ tar xfz mysql-5.6.16.tar.gz
$ sudo /usr/sbin/groupadd -g 1200 mysql
$ sudo /usr/sbin/useradd -r -g mysql -u 1200 mysql
$ cd mysql-5.6.16
$ cmake . -DCMAKE_INSTALL_PREFIX=/opt/mysql/5.6.16 -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_bin -DMYSQL_TCP_PORT=3306
$ make
$ sudo make install
$ sudo chown -R mysql. /opt/mysql
$ cd /opt/mysql/5.6.16/
$ sudo scripts/mysql_install_db --user=mysql
$ sudo chown -R root /opt/mysql/
$ sudo chown -R mysql data
$ sudo cp -a support-files/mysql.server /etc/init.d/mysql
$ sudo chmod +x /etc/init.d/mysql
$ sudo /etc/init.d/mysql start
$ sudo /etc/init.d/mysql stop

Install nginx

$ sudo yum -y install gcc gcc-c++ make zlib-devel pcre-devel openssl-devel
$ sudo /usr/sbin/useradd -r -s /sbin/nologin -u 1001 nginx
$ mkdir src
$ cd src/
$ wget http://nginx.org/download/nginx-1.5.12.tar.gz
$ tar xfx nginx-1.5.12.tar.gz 
$ cd nginx-1.5.12
$ ./configure --prefix=/opt/nginx/1.5.12 \
--with-http_ssl_module \
--user=nginx \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log
$ make
$ sudo make install
$ sudo chown -R nginx. /var/log/nginx
$ sudo vi /etc/init.d/nginx ※1
$ sudo chmod +x /etc/init.d/nginx
$ sudo /sbin/chkconfig --add nginx
$ sudo /sbin/chkconfig --level 345 nginx on
$ sudo /etc/init.d/nginx start

※1

以下のサイトのスクリプトを使用、パスは一部変更
http://wiki.nginx.org/RedHatNginxInitScript

Excelの列番号

PHPExcelでExcelファイルを生成するときに
列番号を自動的にインクリメントしてくれる関数はないようなので、
実装してみた。

public function getRow($index = 1) {
    if($index <= 0) {
        return; //error
    } elseif($index > 26) {
        $first = floor(($index - 1) / 26);
        $second = $index - ($first * 26);
        return chr($first + 64).chr($second + 64);
    } else {
        return chr($index + 64);
    }
}

実行結果

getRow(-1) => ""
getRow(3) => "C"
getRow(26) => "Z"
getRow(27) => "AA"

Doctrine

Doctrineは、Doctrine_QueryではFrom句にサブクエリを指定できないんだね。
少なくとも、ローカルの1.2.4のバージョンではエラーになる。
とりあえず、Doctrine_RawSqlを使って書いてみる。

$q = new Doctrine_RawSql();
$q->addComponent('s', 'Sample')

  • >select('{s.id}, {s.name}, {s.login_at}')
  • >from('(SELECT * FROM Sample s ORDER BY s.login_at desc limit 100) s')
  • >orderBy('rand()')
  • >limit(10);

$q->execute(array(), Doctrine::HYDRATE_ARRAY);

でも一応、FROMでも指定できると書かれているけどね。
サンプルはSELECTとWHEREしかないけど。
http://www.doctrine-project.org/documentation/manual/1_1/en/dql-doctrine-query-language%3Asubqueries

実際のところどうなんでしょうか。

parseInt()

Built-in FunctionのparseIntの引数に"08"や"09"を指定すると、戻り値が"0"になる。
0から始まる文字列の場合は、8進数と見なすためらしい。

数値の8や9を得るためには、第2引数を指定すればよい。

parseInt('08', 10)

https://developer.mozilla.org/ja/Core_JavaScript_1.5_Reference/Global_Functions/parseInt

Tomcatの再起動

tomcatの再起動を一般ユーザ(サーバ管理者以外)でも可能にするために、指定されたディレクトリにファイルを配置すると再起動をするシステムを作ってみた。
cronで毎分ファイルがないかをチェックして、ファイルがあれば再起動するというもので、10分もあれば作れる。
だが、作ってみてサイトトップページへのアクセスした際に、原因不明のエラーになった。(再起動自体はきちんとできているようだ)

調べてみると、文字コードの問題だった。
再起動スクリプトでLANGを設定してあげて、とりあえず解決した。

CRONから起動された場合、LANGの環境変数の値は空になっていたが、サーバの文字コードはLANG=ja_JP.eucJPに設定されている。
デフォルトがEUC_JPじゃないのはまあ当然だろうが、なんだったっけ。