Wstęp
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.
Tworzenie tabeli
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])
Definicja tabeli
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 danych
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"})
Odczyt danych
By odczytać danych używamy :ets.lookup/2
, gdzie wskazujemy tabelę oraz klucz:
:ets.lookup(:table, :key1)
Zwrotnie powinnyśmy otrzymać wynik: [key1: "value1"]
.
Aktualizacja danych
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
.
Usuwanie danych
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)
Usuwanie tabel
Całe tabele usuwamy z pomocą także delete
, ale z arnością /1
:
:ets.delete(:table)
Alternatywne podejście
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).
Podsumowanie
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.