
Ten artykulik będzie nieco krótszy niżeli pozostałe, a to z tego względu, że w teorii nad ETS'em w Elixirze nie ma nadmiernie co się rozpisywać.
W Elixirze, ETS (:ets) to biblioteka, której pełna nazwa brzmi Erlang Term Storage i służy ona jako pewna forma wbudowanego w język cache'u (naprawdę wydajnego cache'u).
W :ets można tworzyć tabele, które potrafią przechowywać spore ilości danych i umożliwiać ich procesowanie.
Tabele w ETS tworzymy z pomocą :ets.new/2, która wymaga nazwy (:atom) i listy opcji definiujących właściwości tabeli.
W Naszym przypadku dodatkowo użyjemy :named_table:
table = :ets.new(:table, [:set, :protected, :named_table])
Możliwe parametry konfiguracji wyglądają tak:
:set Domyślne ustawienie, gdzie każdy klucz jest unikalny.:ordered_set Jak powyższe, ale elementy są posortowane.:bag Zezwolenie na duplikaty kluczy, ale z innymi wartościami.:duplicate_bag Możliwość zduplikowanych kluczy i wartości.:public Każdy proces może wykonywać odczyt i zapis.:protected Każdy proces może czytać, tylko właściciel może zapisywać.:private Tylko proces, który jest włascicielem, może dokonywać odczyt/zapis.:named_table Dzięki tej opcji zyskujemy dostęp to tabeli po jej nazwie, zamiast referencji (zmiennej).Insert wykonujemy z pomocą funkcji :ets.insert/2, w której przekazujemy referencje do tabeli oraz krotkę (ang. tuple), która oczywiście reprezentuje rekord.
Insert powinien Nam zwrócić true:
:ets.insert(:table, {:key1, "value1"})
By odczytać danych używamy :ets.lookup/2, gdzie wskazujemy tabelę oraz klucz:
:ets.lookup(:table, :key1)
Zwrotnie powinnyśmy otrzymać wynik: [key1: "value1"].
ETS nie posiada funkcji update per se. Tak więc by zaktualizować dane, musimy wykonać insert istniejącego już klucza:
:ets.insert(:table, {:key1, "new_val"})
:ets.lookup(:table, :key1)
Wartość oczywiście powinna teraz nosić nazwę new_val.
Dane usuwamy z pomocą :ets.delete/2, gdzie wskazujemy tożsamo jak w poprzednich przykładach tabelę oraz klucz:
:ets.delete(:table, :key1)
:ets.lookup(:table, :key1)
Całe tabele usuwamy z pomocą także delete, ale z arnością /1:
:ets.delete(:table)
Jak już wspomniałem tabele możemy tworzyć w taki sposób, że odwołujemy się do nich :atom'em, ale możemy też to zrobić przy pomocy zmiennej:
my_table = :ets.new(:table, [:set, :public])
:ets.insert(my_table, {:foo, "bar"})
:ets.lookup(my_table, :foo)
Tu wedle uznania, obydwie formy są poprawne (choć ja preferuję tabele imienne).
ETS jest idealnym narzędziem dla scenariuszy, w których potrzebujemy procesować duże wolumeny danych w cache'u na potrzeby Naszej aplikacji lub wykonywać tak zwany state management.
Oczywiście należy pamiętać, że jest to procesowanie w pamięci i w razie potrzeby należy sięgnąć po :dts'a.
Należy także mieć na uwadze, że ETS ograniczony jest pamięcią samej maszyny wirtualnej BEAM VM, oraz, że tabele nie są synchronizowane między procesami, więc sami musimy zadbać o poprawną obsługę danych.