マッチング処理にTokyo Cabinetを使ったら高速すぎて幸福が実現した
1000万件くらいのマスターデータに、50万件くらいのトランザクションデータを突っ込みたい。ただし、挿入できたのと重複したのを把握したい。
MySQLだとどう頑張っても30分くらいかかるので、Tokyo Cabinetを使ってやってみた。
まずはマスターデータ作成。1000万以下の乱数を発生させて、それをキーに、1000万回ストアする。
$ cat tcTest.rb require 'tokyocabinet' include TokyoCabinet db = HDB.new db.open('db.tch', TDB::OWRITER | TDB::OCREAT) 10000000.times{|i| db[rand(10000000)] = 0 } db.close
5分くらいかかった。何件入ったか確認してみる。
$ cat tcTestR.rb require 'tokyocabinet' include TokyoCabinet db = HDB.new db.open('db.tch', TDB::OWRITER | TDB::OCREAT) p db.rnum db.close $ ruby tcTestR.rb 6321134
632万件入った。次はトランザクションデータを作る。
$ seq 1 500000 > 50man.txt
マスターとトランザクションができたので、マッチングさせてみる。
$ cat tcTestS.rb require 'tokyocabinet' include TokyoCabinet db = HDB.new db.open('db.tch', TDB::OWRITER | TDB::OCREAT) dup = File.open("dup.txt", "w") add = File.open("add.txt", "w") File.open("50man.txt"){|file| while line = file.gets if db[line.chomp] == nil then add.puts(line.chomp) db[line.chomp] = 0 else dup.puts(line.chomp) end end } add.close dup.close db.close
$ time ruby tcTestS.rb real 0m12.500s user 0m2.800s sys 0m1.520s
12秒!!! 速え!!!
出力データがちゃんとできたか一応確認する。
$ head add.txt | tr "\n" " "; echo 1 2 6 7 10 11 12 18 19 23 $ head dup.txt | tr "\n" " "; echo 3 4 5 8 9 13 14 15 16 17 $ tail add.txt | tr "\n" " "; echo 499976 499978 499980 499981 499984 499994 499995 499997 499998 500000 $ tail dup.txt | tr "\n" " "; echo 499986 499987 499988 499989 499990 499991 499992 499993 499996 499999
うむ。オッケー。
単純リランしてみる。今度は全てが重複になるはず。
$ time ruby tcTestS.rb real 0m3.010s user 0m2.100s sys 0m0.910s $ diff 50man.txt dup.txt $ wc -l add.txt 0 add.txt
うむ。全部重複になった。オッケー。ていうか全くストアしないと3秒で終わるのかよ!!!