page_adsence

2014年11月20日木曜日

MySQLからMongoDBへのデータ移行 その2

前回、MySQLからMongoDBへの移行作業を書いたが、実際に作業を行うMySQLユーザーにはFILE権限がなかった。
そのため、INTO OUTFILEコマンドが使用出来ず、別の方法を模索することになった。
で、同僚の方から標準出力をファイルに吐きだすという手法を使ってやってみることにした。
やり方自体はすごく簡単で、下記のようにするだけ。

mysql -u ユーザー名 データベース名 -p > output.tsv

これだけで、SQLの結果をTSV形式でファイルに出力することが出来る。
上のコマンドだけというのは少し語弊があるが、上のコマンドを入力すると、パスワードを入力後に入力待ちの状態になる。
この状態で結果をTSV出力したいSQLを流してやると、結果がTSVファイルに出力される。
自分なりにこれをやることでのメリット、デメリットを紹介

■メリット
・MySQLのデータ内に改行やタブが存在していたとしても、\tや\nといった文字列で出力されるため、ファイル上は必ず1レコード1列となっているため、
普通にSQL流した結果の件数と異なっているかどうかをwcコマンドですぐに確認出来る。
また、TSVで出力されるため、MySQLデータ内部にタブが入っていた場合、普通ならずれてしまうが「\t」という文字として出力されるためにそういった問題が起きない。
・ヘッダ行にフィールド名が出力されるため、mongoimportする時に別にファイルを用意する必要が無くなる。

■デメリット
・処理が終わったかどうかがわかりずらい。
入力待ち状態になった後、SQLを入力し、Enterキーを押下するが、改行された後は何も反応がない。
そのため、画面上でSQLが処理を終えたかどうかの判断がつけられない。
対象のコンソール上でわからないだけで、mysqlのSHOW PROCESSLISTコマンドを使用すれば処理が実行されているかどうかはすぐにわかる。
とはいえ、いちいち確認のためにMySQLにログインしてSHOW PROCESSLISTコマンドを打つのは面倒である。
SHOW PROCESSLISTコマンドで、該当のSQLが無くなりSLEEP状態になったら終了しても問題ない。
終了方法としてはexitコマンドを打つだけ。
exitの後にセミコロンをつけると抜けれないらしい。

それ以外の移行方法はほとんど変わらず。
置換の処理方法が異なるので、一応それだけ記載しておく。

cat test.tsv | sed -e 's/"/""/g' | sed -e 's/\t/","/g' | sed -e 's/\(^\|$\)/"/g' | sed -e 's/\(^Z^Z.*app_id=""\([0-9]\+\)"">^Z^Z\|^Z^Z.*^Z^Z\)/\2/g' | sed -e 's/\(^Z\(.*\)^Z\|^Z\(.*\)^Z\)/\2/g' | sed -e 's/\\n/\n/g' | sed -e 's/\\t/\t/g' | sed -e 's/^M//g' | sed -e 's/$/\r/' > convert.csv


あとはmongoimportするだけ。(ヘッダ行が出力されているので、ヘッダファイルは作らなくてもよい)
mongoimport -d freegame_message -c message --type csv --file convert.csv --headerline

とりあえずこんな感じでした。