PROBLEM

  • Elixirをさわりはじめてしばらく経つけどふかく理解した気になれない
  • Phoenixやほかのフレームワークに頼られないケースが出てきたとき自由な発想ができるようになっておきたい
  • 巷でいわれているSLA 99.9999999% などの実際がどうなのか腹落ちしてない

-

SOLUTION

というわけで、LYSE本を読むことにした。Elixirに関係ありそうな箇所を選定している。

  • 今回はインメモリーDBのETSについてかんがえる。

ETSの特徴

  • データへの並列平行なアクセスが可能
    • ただし、安全性と並行性が低下する可能性がある
    • ETSのデフォルト使用数は1400
      • erl -env ERL_MAX_ETS_TABLES Number で設定

ETSのテーブル種類

  • set
    • 標準
  • ordered_set
    • テーブルデータのソート機能あり
    • ユースケース: 範囲指定してデータ取得する (ただし、アクセス時間が遅くなる O(log N))
  • bag
    • 同一キーのタプル(レコード)を保持可能
  • duplicate_bag
    • 同一内容のタプル(レコード)を保持可能
  • 共通機能
    • テーブル所有権
      • ETSテーブル起動関数であらたにコールしたプロセスがそのテーブルの所有者
      • 権限
        • protected level
          • 所有者 read, write
          • その他 read
        • public level
          • 所有者 read, write
          • その他 read, write
        • private level
          • 所有者 read, write
          • その他 n/a
    • テーブルの移譲
      • ETSテーブルはプロセスが死ぬと消滅する
      • 移譲の種類
        • 都度指定する移譲
        • プロセスが死んだ場合の自動移譲

ETSの関数

  • テーブル作成・削除
    • ets:new/2
  • データ挿入・参照
    • ets:insert(Table, ObjectOrObjects)
    • ets:lookup(Table, Key)
  • その他
    • ets:delete(Table, Key)
    • ets:match(Table, MatchClause)
    • ets:match_object(Table, MatchClause)
    • ets:fun2ms(MatchSpecClause)

setテーブルでnamed_tableオプションをつける場合

21> ets:new(ingredients, [set, named_table]).
ingredients
22> ets:insert(ingredients, {bacon, great}).
true
23> ets:lookup(ingredients, bacon).
[{bacon,great}]
24> ets:insert(ingredients, [{bacon, awesome}, {cabbage, alright}]).
true
25> ets:lookup(ingredients, bacon).
[{bacon,awesome}]
26> ets:lookup(ingredients, cabbage).
[{cabbage,alright}]
27> ets:delete(ingredients, cabbage).
true
28> ets:delete(ingredients, cabbage).
true
29> ets:lookup(ingredients, cabbage).
[]
32> ets:insert_new(ingredients, {tomato, hey}).
true
33> ets:insert_new(ingredients, {tomato, hey}).
false

bagテーブルでnamed_tableオプションをつけない場合

34> TabId = ets:new(ingredients, [bag]).
16401
35> ets:insert(TabId, {bacon, delicious}).
true
36> ets:insert(TabId, {bacon, fat}).
true
37> ets:insert(TabId, {bacon, fat}).
true
38> ets:lookup(TabId, bacon).
[{bacon,delicious},{bacon,fat}]

ordered_setターブルで、named_tableオプションをつける場合

42> ets:new(ingredients, [ordered_set, named_table]).
ingredients
43> ets:insert(ingredients, [{ketchup, "not much"}, {mustard, "a lot"}, {cheese, "yes", "goat"}, {patty, "moose"}, {onions, "a lot", "caramelized"}]).
true
44> Res1 = ets:first(ingredients).
cheese
45> Res2 = ets:next(ingredients, Res1).
ketchup
46> Res3 = ets:next(ingredients, Res2).
mustard
47> ets:last(ingredients).
patty
48> ets:prev(ingredients, ets:last(ingredients)).
onions

named_tableオプションつきbagテーブルでパターンマッチをする

53> ets:new(table, [named_table, bag]).
table
54> ets:insert(table, [{items, a, b, c, d}, {items, a, b, c, a}, {cat, brown, soft, loveable, selfish}, {friends, [jem, jeff, etc]}, {items, 1, 2, 3, 1}]).
true
55> ets:match(table, {items, '$1', '$2', '_', '$1'}).
[[a,b],[1,2]]
56> ets:match(table, {items, '$114', '$212', '_', '$6'}).
[[d,a,b],[a,a,b],[1,1,2]]
57> ets:match_object(table, {items, '$1', '$2', '_', '$1'}).
[{items,a,b,c,a},{items,1,2,3,1}]
58> ets:delete(table).
true

-

以上 :droplet: