マッチング処理に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秒で終わるのかよ!!!