AttsuBlog

ATTSU INC. Official Blog
IMGP1391
0 comments

ArangoDBとClojure その4

タグ:, , ,

お久しぶりです、萬屋です(^_^;)

すっかり更新を疎かにしていました……気付けば梅雨になって雨が降ったり止んだりですね〜

個人的に雨は嫌いではないです(部屋の中から見ているには)。
雨の音や水の跳ねる音なんかを部屋でぼーっと聴いていると風流な感じがしますね(・∀・)

元々中国では「黴雨(ばいう)」という字だったそうです。字のままですね、カビの多い時期ということなのでしょう。
これを季節に合わせて(梅雨の時期は梅の実が熟す時期)「梅雨」にした、とも言われているそうです(語源には色々な説があります)
季節を楽しむ日本人らしい良い字だな〜と思いました(^^)
雨ばかりで嫌になるよりも、雨を楽しむ、そんな心のゆとりが持てたらいいなぁ……

さてさて、閑話休題、暫く書いていなかったClojureとArangoDB第四弾!
今回は以前少しお話したArangoDBの速度とIndexの話をしてみようかと思います(^^ゞ

以前の記事に単純な値を取得するのであれば、AQLよりby-exampleの方が速い、と書きました。
それを実証してみたいと思います(`・ω・´)ゞ

まずArangoDBに「bench_test」というDBを作成して1000件、10000件、100000件のデータが入ったコレクションを作成します。


(def db-name "bench_test")
(def arango-host "http://127.0.0.1:8529/")
(def CTX {:conn {:type :simple
                 :url arango-host
                 :uname "root"
                 :password ""}
          :db db-name})
(def loopcount1 (vec (range 1000)))
(def loopcount2 (vec (range 10000)))
(def loopcount3 (vec (range 100000)))

(defn create-context
  "Create Context"
  [ctx]
  (conj ctx CTX))

(defn create-data
  [i collection]
  (let [params (create-context {:in-collection collection
                                :payload {:name (str "name" i)}})
        result (doc/create params)]
    (if (= true (result :error))
      (println (str "エラー" i)))))

(defn -main
  [& args]
  (doseq [i loopcount1] (create-data i "check1"))
  (doseq [i loopcount2] (create-data i "check2"))
  (doseq [i loopcount3] (create-data i "check3")))

これでcheck1, check2, check3にデータが入りましたε-(´∀`*)
require文などは省略していますので悪しからず……

Clojureでベンチマークを取るときの強いお供をご紹介します!「criterium」です( ゚Д゚ノノ☆パチパチパチパチ
benchという関数で簡単に測ってくれます〜project.cljのdependenciesに追加してlein depsでおkです!

はい、では実際にベンチを測った時のコードは以下になります。


(defn create-example-params
  [collection name]
  (create-context {:payload {:collection collection
                             :example {:name name}}}))

(defn create-aql-params
  [collection name]
  (create-context {:payload {:query (str "FOR c IN " collection " FILTER c.name == '" name "' RETURN c")}}))

(defn get-data-example
  [params]
  (q/by-example-first params))

(defn get-data-aql
  [params]
  (q/aql-query params))

(defn -main
  [& args]
  (let [params (create-example-params "check1" "name756")]
    (bench (get-data-example params)))
  (let [params (create-aql-params "check1" "name756")]
    (bench (get-data-aql params)))

  (let [params (create-example-params "check2" "name5567")]
    (bench (get-data-example params)))
  (let [params (create-aql-params "check2" "name5567")]
    (bench (get-data-aql params)))

  (let [params (create-example-params "check3" "name12345")]
    (bench (get-data-example params)))
  (let [params (create-aql-params "check3" "name12345")]
    (bench (get-data-aql params))))

create-contextなどの関数は上のコードなどを参考にして下さいねヽ(゚д゚)ノ

check1, check2, check3のコレクションから適当なやつをby-exampleとAQLを使って取得しています。ベンチをとるという意味ではあまり厳密なことはやっていませんが、違いを見るというだけであればこれで十分かと思います(;・∀・)というのもこの結果を見れば一目瞭然なのです!ででん!!


# 1000件のところからby-example
Evaluation count : 22560 in 60 samples of 376 calls.
             Execution time mean : 2.683895 ms
    Execution time std-deviation : 176.988242 µs
   Execution time lower quantile : 2.523526 ms ( 2.5%)
   Execution time upper quantile : 2.794545 ms (97.5%)
                   Overhead used : 1.890001 ns
# 1000件のところからAQL 
Evaluation count : 12180 in 60 samples of 203 calls.
             Execution time mean : 4.964391 ms
    Execution time std-deviation : 117.164479 µs
   Execution time lower quantile : 4.823986 ms ( 2.5%)
   Execution time upper quantile : 5.117278 ms (97.5%)
                   Overhead used : 1.890001 ns

# 10000件のところからby-example
Evaluation count : 11640 in 60 samples of 194 calls.
             Execution time mean : 5.318444 ms
    Execution time std-deviation : 211.448285 µs
   Execution time lower quantile : 4.993717 ms ( 2.5%)
   Execution time upper quantile : 5.578816 ms (97.5%)
                   Overhead used : 1.890001 ns
# 10000件のところからAQL
Evaluation count : 2340 in 60 samples of 39 calls.
             Execution time mean : 26.260912 ms
    Execution time std-deviation : 325.417321 µs
   Execution time lower quantile : 25.679591 ms ( 2.5%)
   Execution time upper quantile : 26.803539 ms (97.5%)
                   Overhead used : 1.890001 ns
                   
# 100000件のところからby-example
Evaluation count : 1740 in 60 samples of 29 calls.
             Execution time mean : 36.391516 ms
    Execution time std-deviation : 258.631714 µs
   Execution time lower quantile : 35.954974 ms ( 2.5%)
   Execution time upper quantile : 37.002142 ms (97.5%)
                   Overhead used : 1.890001 ns
# 100000件のところからAQL
Evaluation count : 300 in 60 samples of 5 calls.
             Execution time mean : 230.698103 ms
    Execution time std-deviation : 3.911249 ms
   Execution time lower quantile : 223.780211 ms ( 2.5%)
   Execution time upper quantile : 237.779458 ms (97.5%)
                   Overhead used : 1.890001 ns

1000件のコレクションからでも2msくらいの違い、100000件の時は顕著ですね、200msも違うΣ(゚Д゚)

おーけーおーけー、遅いって言いたいんだろ?(ドヤァァ

そうですね、DBにはIndexをつけて速くするのは当たり前の手段ですね!
では、それぞれのコレクションのnameにIndexをつけてみたいと思いますε=(ノ゚д゚)ノ

Arangosh(ArangoDBのコマンドライン操作)で行って下さい。


> db.check1.ensureIndex({ type: "hash", fields: [ "name" ], unique: false });
> db.check2.ensureIndex({ type: "hash", fields: [ "name" ], unique: false });
> db.check3.ensureIndex({ type: "hash", fields: [ "name" ], unique: false });

これで準備完了だブラザー、さっきのソースを動かしてみますε-(/・ω・)/


# 1000件のところからby-example
Evaluation count : 25140 in 60 samples of 419 calls.
             Execution time mean : 2.514471 ms
    Execution time std-deviation : 96.801232 µs
   Execution time lower quantile : 2.337052 ms ( 2.5%)
   Execution time upper quantile : 2.766415 ms (97.5%)
                   Overhead used : 1.924799 ns
# 1000件のところからAQL 
Evaluation count : 23820 in 60 samples of 397 calls.
             Execution time mean : 2.533823 ms
    Execution time std-deviation : 77.621516 µs
   Execution time lower quantile : 2.352586 ms ( 2.5%)
   Execution time upper quantile : 2.639155 ms (97.5%)
                   Overhead used : 1.924799 ns

# 10000件のところからby-example
Evaluation count : 23760 in 60 samples of 396 calls.
             Execution time mean : 2.371367 ms
    Execution time std-deviation : 59.795864 µs
   Execution time lower quantile : 2.294667 ms ( 2.5%)
   Execution time upper quantile : 2.475907 ms (97.5%)
                   Overhead used : 1.924799 ns
# 10000件のところからAQL
Evaluation count : 25500 in 60 samples of 425 calls.
             Execution time mean : 2.562090 ms
    Execution time std-deviation : 75.300263 µs
   Execution time lower quantile : 2.490612 ms ( 2.5%)
   Execution time upper quantile : 2.685703 ms (97.5%)
                   Overhead used : 1.924799 ns
                   
# 100000件のところからby-example
Evaluation count : 25140 in 60 samples of 419 calls.
             Execution time mean : 2.495643 ms
    Execution time std-deviation : 71.650757 µs
   Execution time lower quantile : 2.293765 ms ( 2.5%)
   Execution time upper quantile : 2.571155 ms (97.5%)
                   Overhead used : 1.924799 ns
# 100000件のところからAQL
Evaluation count : 23760 in 60 samples of 396 calls.
             Execution time mean : 2.510637 ms
    Execution time std-deviation : 130.358769 µs
   Execution time lower quantile : 2.339675 ms ( 2.5%)
   Execution time upper quantile : 2.825150 ms (97.5%)
                   Overhead used : 1.924799 ns

本気かブラザー……爆速になりすぎだろ( ;´Д`)
こうなるとby-exampleもAQLもほとんど変わりませんね……

もっと大量のデータでもやってみたいですね〜
っとまぁ目的は果たしたので今日はこのへんで(@^^)/~~~

P.S
おまけ、ArangoDBにFullTextSearchという機能があります。
この機能を使うにはFullTextSearch用のIndexをはらないといけないのですがやり方は以下の通りです。


db.item.ensureIndex({ type: "fulltext", fields: [ "title" ] });

ただしfieldsに複数入れることは出来ないです……

インデックスつながりで一応こちらもご紹介(;´∀`)
これについての詳細も今度書きたいですねぇ……


Leave A Comment