W dzisiejszych czasach, projektując jakąkolwiek aplikację, zawsze musimy brać pod uwagę przechowywanie danych oraz ich przetwarzanie. Jakby nie patrzeć przecież całe dziedziny technologii komputerowych skupiają się właśnie na tym zagadnieniu – przetwarzaniu i wymianie danych. Czy są to dane pobierane bezpośrednio od użytkownika i przetwarzane na żądanie (jak na przykład w kalkulatorze), czy dane zbierane w procesie ciągłym i poddawane ciągłej analizie (przykładowo analiza dostarczana przez Google Trends), czy chociażby olbrzymie ilości danych przetwarzanych i wykorzystywanych w celach uczenia maszynowego. Płynie z tego jeden ważny wniosek, aby większość aplikacji mogło działać zgodnie ze swoim przeznaczeniem, muszą one korzystać z jakiegoś miejsca, z którego będzie można pobierać, zapisywać oraz usuwać dane. Takimi konstrukcjami są bazy danych, o których na pewno słyszała każda osoba zajmująca się pracą w dziedzinie technologii informacyjnych. Dla tych osób, które nie zajmują się programowaniem na co dzień (a są zainteresowane tematyką relacyjnych i nierelacyjnych baz danych), krótka definicja – bazy danych (w ujęciu cyfrowym) są to zorganizowane struktury zebranych danych cyfrowych, które zarządzane są poprzez DBMS-y (Database management system). DBMS umożliwia korzystanie z danych użytkownikowi oraz aplikacji – dzięki niemu jesteśmy w stanie tworzyć, odczytywać, usuwać oraz aktualizować dane przechowywane w bazie danych. Jest to swojego rodzaju interfejs pomiędzy użytkownikiem (aplikacją), a bazą danych. Przykładem może być jeden z najbardziej znanych DBMS dla baz danych – SQL, używanych w relacyjnych bazach danych.
Rys. 1 Schemat działania baz danych, DBMS oraz użytkowników.
Istnieją różne rodzaje DBMS-ów, przykładami mogą być chociażby:
– RDBMS, czyli relacyjne bazy danych (np. SQL),
– NoSQL, nierelacyjne bazy danych, czyli struktury o słabo zdefiniowanej strukturze,
– IMDBMS (In-memory database management system) system zarządzania bazami danych w pamięci, gwarantujący szybszą odpowiedź i lepsza wydajność.
W tym artykule zajmiemy się porównaniem dwóch z nich – relacyjnych baz danych, których implementacje są najczęściej wykorzystywane podczas zarządzania danymi, oraz nierelacyjne bazy danych (i ich podtypy), które ostatnimi czasy znacząco zyskują na popularności wśród twórców oprogramowania. Zapraszam do lektury!
Na samym początku przyjrzyjmy się bliżej relacyjnemu modelowi baz danych. Ich ojcem jest E.F Codd, który w 1970 pracując w firmie IBM zaproponował, aby dane cyfrowe były przechowywane w sposób relacyjny (oznacza to, że struktura danych w sobie krotki (Tuple), które reprezentują pojedyncze rekordy w bazie, oraz relacje pomiędzy poszczególnymi krotkami w tabelach).
Rys. 2 Schemat ogólny relacyjnej bazy danych.
W uproszczeniu model relacyjny przedstawiany można sobie wyobrazić, jako dwie lub więcej tabel zawierających rekordy (rekord jest wierszem w tabeli) oraz klucze, przez które można łączyć ze sobą dwie tabele. Przykładem może być tabela zawierająca w sobie dane na temat pracowników firmy i ich stanowiska, połączone z tabelą na temat zarobków na tych stanowiskach. Aby połączyć obie tabele i odczytać wynagrodzenie dla danego pracownika musimy połączyć je za pomocą klucza głównego (np. indywidualnego numeru identyfikacyjnego dla stanowiska), przy czym należy pamiętać, że wielu pracowników może zajmować to samo stanowisko (np. możemy mieć kilku młodszych programistów). Aby łatwiej było to zrozumieć spójrzmy na ilustrację:
Rys. 3 Rozszerzony przykład z tekstu powyżej. Ze schematu możemy odczytać relacje pomiędzy poszczególnymi tabelami (np. że pracownik jest połączony z pokojem poprzez Id pokoju z tabeli Pracownicy i Id z tabeli pokoje.
Językiem komunikacji dla praktycznie wszystkich relacyjnych baz danych jest SQL (Structured Query Language). W bazach relacyjnych typ danych przechowywanych musi być jasno zdefiniowany, wszystkie dane przechowywane muszą być uporządkowane w ściśle zorganizowany sposób. Dzięki temu dane przechowywane w tego rodzaju bazach danych zawsze muszą być zgodne we wszystkich tabelach, inaczej nie będzie możliwe np. dodanie rekordu (przykładowo przez to, że dla pracownika nie istnieje dane stanowisko), co jest bardzo ważne chociażby przy zapisywaniu transakcji finansowych. Dodatkowo tego typu sztywna struktura bazy powoduje minimalizacje zbędnych danych w niej przechowywanych.
W opozycji do relacyjnych baz danych stoją nierelacyjne bazy danych – NoSQL (odwołujące się do „not only SQL”).
Bazy klucz – wartość (key – value database), są najprostsze w porównaniu do innych typów. Ich działanie opiera się na tworzeniu i składowaniu par klucz – wartość, oraz pobieraniu tych wartości poprzez znany i podany klucz. Nie są one najczęściej odpowiednie do dużych aplikacji, aczkolwiek ich prostota i szybkość działania sprawia że są one atrakcyjne w niektórych rozwiązaniach (np. systemach wbudowanych, komentarzy pod blogami/artykułami, kategoriami produktu w e-commerce itd.). Przykładami wykorzystania tego typu są systemy Redis, Memcached, Voldemorte, Oracle NoSQL Database.
Bazy kolumnowe (Wide Column Stores), nazywane również, jako rozszerzalne magazyny rekordów. Przechowują one dane w rekordach, które są zdolne do pomieszczenia bardzo dużej ilości dynamicznych kolumn. Struktura w takich bazach nie musi być sztywna – oznacza to, iż nazwy kolumn nie muszą być uprzednio zdefiniowane. Warto pamiętać, że operacje wyszukania w takich kolumnach są dużo szybsze – wyszukiwanie odbywa się tylko po wybranych przez nas kolumnach, w odróżnieniu do przeszukiwania wszystkich pół poszczególnych rekordów. Ważny jest również sposób zapisania danych na dysku twardym, w przypadku zapisu danych z bazy kolumnowej, wszystkie dane z danej kolumny są zapisane „obok” siebie, przez co ich odczyt może się odbyć w pojedynczym odczycie dysku. W przypadku relacyjnej bazy danych zapisywane obok siebie są poszczególne rzędy – z tego powodu odczyt danych może być zdecydowanie wolniejszy. Przykładami mogą być HBase, Hypertable, Google Bigtable.
Rys. 4 Porównanie bazy rzędowej i kolumnowej na przykładzie z wykorzystaniem Excela do wizualizacji. Jak widać dane w bazie kolumnowej przechowywane są jako pierwsza kolumna: {wszystkieImiona}, druga kolumna: {wszyskieNazwiska}. trzecia kolumna: {wiek}.
Bazy dokumentowe (Document databases) – przypominają trochę bazy typu klucz – wartość, tylko że zamiast wartości przechowywane są w nich dokumenty (np. w formacie XML, JSON, bądź BSON). Dokumenty te zawierają w sobie opisaną swoją strukturę (tak jak to wygląda w plikach typu JSON) oraz wartości, struktura ta nie jest z góry narzucana przez schemat. Dokumenty te przechowywane są w zbiorach, które są nazywane kolekcjami. Jest to swoisty odpowiednik tabeli oraz rekordów z relacyjnej bazy danych, ale zamiast tabel występują kolekcje, a zamiast rekordów dokumenty. Ważne jest, że dokumenty znajdujące się w tej samej kolekcji nie muszą mieć tej samej struktury, mogą się one różnić poziomem skomplikowania, oraz nazwami kolumn.
Rys. 5 Schemat dokumentowej bazy danych.
Rys. 6 Dwa różne obiekty typu JSON, które możemy przechowywać w jednej kolekcji w dokumentowej bazie danych.
Taki sposób składowania danych sprzyja łatwemu skalowaniu architektury i szybkiemu dostępowi do przechowywanych danych. Używany jest on na przykład przy składowaniu logów wydarzeń, w analizie licznych nagromadzonych danych, oraz jest również bardzo często wykorzystywany w e-commerce, przy „wózku zakupowym” (z którego na pewno nie jeden raz zdarzyło Ci się korzystać). Znanymi dostawcami są tutaj MongoDB (bardzo popularna), CouchDB, Microsoft Azure Cosmos DB.
Bazy oparte na grafach (Graph Databases) – jak sama nazwa wskazuje, te bazy danych opierają się na przechowywaniu danych w postaci struktur grafów. W odróżnieniu od innych baz danych posiadają one wskaźnik to pobliskich połączonych elementów, dlatego przeszukiwanie tego typu baz danych odbywa się bez wykorzystania indeksu. Każdy element nazywany jest węzłem (node), a połączenia nazywane są krawędziemi (edges). W bazach tego typu najważniejsze są relacje, a połączenia bywają opisywane, jako rzeczownik – czasownik – rzeczownik (noun – verb – noun). Należy również wspomnieć, że węzeł może zawierać kilka informacji, np. wiek użytkownika, imię użytkownika oraz nazwisko. Jako przykład możemy wziąć przechowywanie danych o kierowcy i jego samochodzie: Jan Kowalski (węzeł, rzeczownik) posiada (relacja, czasownik) Toyotę (węzeł, rzeczownik). Głównymi zaletami tego typu sposobu przechowywania danych jest szybkość działania, skalowalność, elastyczność oraz łatwość przedstawiania relacji pomiędzy elementami (jak i łatwość w tłumaczeniu wymagań biznesowych). Są one używane np. w detekcji oszustw finansowych (fraud) oraz w mapowaniu interakcji socjalnych pomiędzy użytkownikami sieci społecznościowych. Przykładami mogą być Neo4j, FlockDB, OrientDB.
Rys. 7 Schemat wyglądu bazy danych opartych o grafy.
Po wstępnym przedstawieniu poszczególnych typów baz danych czas przejść do sedna, czyli którą z nich wybrać podczas tworzenia projektu? Oczywiście na samym wstępie należy zauważyć, że nie ma jednoznacznie najlepszego typu bazy danych. Każda z nich oferuje inne możliwości i to właśnie w zależności od tego, czego potrzebujemy powinniśmy uzależniać nasze wybory. Pierwszym kryterium, które powinniśmy brać pod uwagę, jest to czy musimy zapewnić spójność, izolację, trwałość oraz niepodzielność (ACID), czyli zbiór właściwości gwarantujących poprawne przetwarzanie transakcji w bazach danych. Zazwyczaj bazy NoSQL poświęcają te wartości na rzecz szybkości oraz elastyczności, dlatego w systemach gdzie jest wymagany ACID (np. systemy bankowe), relacyjne bazy danych dalej pozostają preferowanym wyborem. Kolejnym kryterium powinno być to czy rzeczywiście potrzebujemy funkcjonalności oferowanej przez bazy NoSQL, jeżeli przechowywane przez nas dane są ustrukturyzowane oraz niezmienne, a nasza aplikacja nie doświadcza ogromnego wzrostu w krótkim czasie, to być może po prostu nie ma sensu zamieniać tradycyjnej bazy relacyjnej na bazę NoSQL. Jeżeli natomiast musimy mieścić duże ilości danych, które nie posiadają z góry określonej struktury, to prawdopodobnie najlepszym wyborem okażą się bazy NoSQL-owe. Zagwarantują one nam łatwość rozbudowania platformy, szybszy dostęp do danych, oraz łatwość gromadzenia danych, które nie posiadają określonej struktury. Następnym kryterium może być szybkość usprawniania i zmieniania aplikacji. W przypadku baz NoSQL bazy danych nie muszą być uprzednio przygotowane do pracy, nie musimy również korzystać z pracy administratora bazy danych. Wszystkie zmiany mogą być wprowadzane szybko i bezboleśnie, natomiast prototypy aplikacji mogą powstawać w bardzo krótkich ramach czasowych. Ostatnią rzeczą, na którą możemy zwrócić uwagę jest sposób wykorzystania danych. Jeżeli zależy nam na tym, aby analizować dane w czasie rzeczywistym, to z pewnością powinniśmy zainteresować się bazami NoSQL. Jeżeli natomiast nasze dane mają być wykorzystywane głównie do raportowania (mającego duże wymagania odnośnie jakości), to z dużą dozą pewności preferowanym wyborem powinny być bazy relacyjne.
Jak widać, technologie przechowywania danych z każdym kolejnym rokiem oferują coraz ciekawsze rozwiązania, które można dopasować bezpośrednio do swoich wymagań. Nie ma metod lepszych i gorszych, są tylko te, które w danym momencie pasują nam lepiej albo gorzej. Warto jednak zainteresować się tematem baz danych NoSQL, gdyż jest to jedna z najszybciej rozwijających się ostatnio dziedzin na rynku IT. Jeżeli macie jakieś uwagi lub spostrzeżenia – zapraszamy do komentowania, bądź pisania bezpośrednio do mnie na adres e-mail marek.makuch@it-leaders.pl. Do przeczytania w następnym artykule!