巨大なデータファイルの数行に一行がほしいということがあります。

たとえば、1分おきに記録されている元データがあるけど、実際には1時間に一回のデータが見られればいいという場合、60行につき1行のデータがとれれば事足りるという具合です。


result = ""

idx = 0
File.open('./src.csv', 'r') do |f|
    f.each_slice(10000) do |chunk|
        result += chunk[0].to_s
        puts idx	#check progress
        idx += 1
    end
end

File.open("./output.csv", 'w') do |f|
    f.puts result
end

肝は io.each_slice(n)メソッドを使うことです。

もともとのsrc.csvは1億2千万行を保持するファイルですが、each_slice(10000)を使うことによって、1万件のデータをひとかたまり(chunk)として取り出し、その1行目をresultに追記していくことで1万行につき一行を取り出すということをやっています。

この方法だと、メモリの使用量も全行を読み出すのに比べてずいぶん節約できているようでした。

スクリプトを回して10秒ちょっとくらいで無事、1万2千件のデータがoutput.csvに保存されました。




neovimでコーディングしようと思ったところ、deinのneosnippetの更新がうまくいかないことに気づいた。

設定ファイルを見てみるも、特に異常が見当たらない

んー?と思って

neovim内で

:UpdateRemotePlugins

を実行してみる。

動かない、どころか、neovim起動時にダラダラとエラーを吐くようにまでなってしまったw

これからコード書こうと思ったのにー!うわああああ/(^o^)\オワタ

と思いつつも、冷静に何が悪いのかを推察してみる。

ひょっとしてdeinの設定ファイル見てる最中にどっかいじったのかなー、だとしたらこれバックアップ取ってないんですけどー!うわああああdein入れ直し\(^o^)/オワタ

ととても冷静と言える状態ではなかったが、

deoplete.nvimが効かなくなった時の手元できる対処法

というサイトを発見したので、まずはneovimに入って
:CheckHealth

をしてみると、どうやらpython3のproviderがエラーとなっている様子

ほうほう、なにかが変わってしまったのだろう。

と思いつつpython3のneovimの更新をかけてみる

pip install neovim

その後、もういちどCheckHealthをかけるとエラーが消えてる!やったー!

と思ったけどまだ、まともには動かない。

その後、

:call dein#update()

をかけると動くようになった。

よかったーと思うとともに、これからdeinの設定ファイルのバックアップを可及的速やかに取ります。

上記サイトの管理人さんありがとうございました




1億2千万行のcsvデータをデータベースに保管したくなったので、rubyを使ってデータベース(Mysql)に挿入した。

gem install mysql

でrubyのmysqlライブラリを入れようとしたら

libmysqlclient-dev を先にaptでインストールするべしとのお告げを得たので

sudo apt install libmysqlclient-dev

でまずはlibmysqlclient-devをインストール

その後

gem install mysql

で無事gemが入った

以下mysqlDBにファイルからデータをINSERTするのに使ったコードです。

#!/usr/bin/ruby

require 'mysql'

client = Mysql::new("127.0.0.1", "username", "password", "db-name")

# set charcter code UTF-8
client.query("set character set utf8")

File.open('./source.csv', 'r') do |f|
    f.each_slice(1000) do |chunk|
        chunk.each do |lines|
			# chop() cuts "\n" end of line
            buf = lines.chop.split(',')
            client.query("INSERT INTO test(time,price,amount) VALUES(#{buf[0]},#{buf[1]},#{buf[2]});")
        end
    end
end

client.close

io.each_slice(1000)

普通のeachを使うと一行ずつの処理になってしまい、時間もかかるものと思われるが、each_slice(n)によってnの数分だけ一気に処理を行うことができる。

nの数は各々のメモリ搭載量に合わせて変更していただければと思います。

ただ想定外だったのは、これでも一万件のレコードを挿入するのにおよそ1分くらいかかってしまうこと

単純に計算して1億2千万件のレコードを挿入し終えるのは166時間以上の時間が必要ということになる…

NOSQLデータベースだったらもっと早いんだろうね。

そのうちそっち方面も探っていきたい