にむかひて

ectoとETSの速度差

2022年4月 トップ > ひとこと > 調査したことの記録
#Elixir #Ecto #ETS

知りたいこと

  • 処理中に何回も読みにいくレコードが大量にあって、それを先にメモリに載せて置いたらどのくらい早くなるだろう
  • つまり、Ecto.Repo.get():ets.lookup() の差
  • とりあえずid走査でどうなるかやってみる
  • DBは最適化というほど頑張っていない

以下、リソースをUserとしたときの疑似コード

共通処理

  • 先に全レコードを読んでレコードを読んでidをシャッフルしておく
users = Repo.all(User)
ids = Enum.map(users, & &1.id) |> Enum.shuffle()

Ecto

ids
|> Flow.from_enumerable()
|> Flow.map(& Repo.get(User, &1))
|> Enum.to_list()

:ets

table = :ets.new(:lookup, [:set, :public])

users
|> Enum.each(fn user ->
  :ets.insert_new(table, {user.id, user})
end)

ids
|> Flow.from_enumerable()
|> Flow.map(& :ets.lookup(table, &1))
|> Enum.to_list()

結果

  • 15万件では特に Ecto:ETS=2:1 くらいの時間差だった。ETSが速い
  • 今回は一回きりのアクセスで、:ets.insert_new() も計測に含めており、そちらに時間がかかっている面がある
    • :ets.lookup だけならば、4:1 くらいになった
    • 余談で、insert_new()をFlowでしてみたときに遅くなったのでひょっとすると何か変かもしれない
  • 用途によっては、ETSを検討する価値がありそう
    • 余談で :ets.match() は遅かった

サイト内検索