2.1 Pojawienie się terminu NoSQL

Ostatnio bardzo modny i popularny stał się termin „NoSQL”, pod tym znakiem aktywnie rozwijane i promowane są wszelkiego rodzaju rozwiązania programistyczne. NoSQL stał się synonimem ogromnych ilości danych, skalowalności liniowej, klastrów, tolerancji błędów, nierelacyjności. Jednak niewiele osób dobrze rozumie, czym jest pamięć masowa NoSQL, jak pojawił się ten termin i jakie mają wspólne cechy. Spróbujmy wypełnić tę lukę.

Najciekawsze w tym pojęciu jest to, że choć po raz pierwszy użyto go pod koniec lat 90., to w obecnej formie nabrało prawdziwego znaczenia dopiero w połowie 2009 r. Początkowo była to nazwa otwartego -source baza danych stworzona przez Carlo Strozziego, która przechowywała wszystkie dane jako pliki ASCII i używała skryptów powłoki zamiast SQL, aby uzyskać dostęp do danych. Nie miało to nic wspólnego z „NoSQL” w jego obecnej formie.

W czerwcu 2009 roku Johan Oskarsson zorganizował w San Francisco spotkanie w celu omówienia nowych trendów na rynku pamięci masowej i przetwarzania IT. Głównym impulsem do spotkania były nowe produkty open source, takie jak BigTable i Dynamo. Aby uzyskać jasną zapowiedź spotkania, trzeba było znaleźć pojemne i zwięzłe określenie, które idealnie wpasuje się w hashtag Twittera. Jedno z tych określeń zostało zaproponowane przez Erica Evansa z RackSpace – „NoSQL”. Termin był zaplanowany tylko na jedno spotkanie i nie miał głębokiego ładunku semantycznego, ale tak się złożyło, że jak wirusowa reklama rozprzestrzenił się po globalnej sieci i stał się de facto nazwą całego trendu w branży IT. Nawiasem mówiąc, na konferencji przemawiali Voldemort (klon Amazon Dynamo), Cassandra, Hbase (analogi Google BigTable), Hypertable, CouchDB, MongoDB.

Warto jeszcze raz podkreślić, że termin „NoSQL” ma całkowicie spontaniczne pochodzenie i nie ma za sobą ogólnie przyjętej definicji ani instytucji naukowej. Nazwa ta charakteryzuje raczej wektor rozwoju IT z dala od relacyjnych baz danych. To skrót od Not Only SQL, chociaż są zwolennicy bezpośredniej definicji No SQL. Pramod Sadalaj i Martin Fowler próbowali pogrupować i usystematyzować wiedzę o świecie NoSQL w swojej najnowszej książce „NoSQL Distilled”.

2.2 Podstawowe cechy baz NoSQL

Istnieje kilka wspólnych cech dla wszystkich NoSQL, ponieważ wiele systemów heterogenicznych jest teraz ukrytych pod etykietą NoSQL (być może najbardziej kompletną listę można znaleźć na stronie http://nosql-database.org/). Wiele cech jest charakterystycznych tylko dla niektórych baz danych NoSQL, na pewno wspomnę o tym przy wymienianiu.

1. Nie jest używany żaden SQL

Mam na myśli ANSI SQL DML, ponieważ wiele baz danych próbuje używać języków zapytań podobnych do dobrze znanej ulubionej składni, ale nikomu nie udało się tego w pełni zaimplementować i raczej się to nie uda. Chociaż istnieją pogłoski o startupach, które próbują zaimplementować SQL, na przykład w hadup ( http://www.drawntoscalehq.com/ i http://www.hadapt.com/ ).

2. Nieustrukturyzowane (bez schematów)

Oznacza to, że w bazach NoSQL, w przeciwieństwie do baz relacyjnych, struktura danych nie jest uregulowana (lub słabo typowana, jeśli rysujemy analogie z językami programowania) - można dodać dowolne pole w osobnej linii lub dokumencie bez uprzedniej deklaratywnej zmiany struktury całego stołu. Zatem jeśli zachodzi potrzeba zmiany modelu danych, to jedynym wystarczającym działaniem jest odzwierciedlenie zmiany w kodzie aplikacji.

Na przykład podczas zmiany nazwy pola w MongoDB:

BasicDBObject order = new BasicDBObject();
order.put("date", orderDate); // this field was a long time ago
order.put("totalSum", total); // before we just used "sum"

Jeśli zmienimy logikę aplikacji, to spodziewamy się nowego pola również podczas czytania. Jednak ze względu na brak schematu danych w innych już istniejących obiektach Order brakuje pola totalSum. W tej sytuacji są dwa warianty dalszego postępowania.

Pierwszy polega na przeszukaniu wszystkich dokumentów i zaktualizowaniu tego pola we wszystkich istniejących dokumentach. Ze względu na ilość danych proces ten odbywa się bez żadnych blokad (podobnie jak komenda alter table rename column), więc podczas aktualizacji już istniejące dane mogą być odczytywane przez inne procesy. Dlatego druga opcja - sprawdzenie kodu aplikacji - jest nieunikniona:

BasicDBObject order = new BasicDBObject();
Double totalSum = order.getDouble("sum"); // This is the old model
if (totalSum  == null)
totalSum = order.getDouble("totalSum"); // This is the updated model

I już przy ponownym zapisie zapiszemy to pole do bazy danych w nowym formacie.

Przyjemną konsekwencją braku schematu jest efektywność pracy z rzadkimi danymi. Jeśli jeden dokument ma pole date_published, a drugi nie, to dla drugiego nie zostanie utworzone żadne puste pole date_published. Jest to w zasadzie logiczne, ale mniej oczywistym przykładem są bazy danych NoSQL z rodziny kolumn, które wykorzystują znane pojęcia tabel/kolumn. Jednak ze względu na brak schematu kolumny nie są deklarowane deklaratywnie i mogą być zmieniane/dodawane podczas sesji użytkownika z bazą danych. Pozwala to w szczególności na wykorzystanie kolumn dynamicznych do realizacji zestawień.

Schemat nieustrukturyzowany ma swoje wady - oprócz wspomnianego wyżej narzutu w kodzie aplikacji przy zmianie modelu danych - brak wszelkiego rodzaju ograniczeń od bazy (not null, unique, check constraint itp.), plus tam występują dodatkowe trudności w zrozumieniu i kontrolowaniu danych strukturalnych podczas równoległej pracy z bazą danych różnych projektów (brak słowników po stronie bazy danych). Jednak w szybko zmieniającym się współczesnym świecie taka elastyczność jest nadal zaletą. Przykładem jest Twitter, który pięć lat temu wraz z tweetem przechowywał tylko trochę dodatkowych informacji (czas, uchwyt Twittera i jeszcze kilka bajtów metainformacji), ale teraz, oprócz samej wiadomości, jeszcze kilka kilobajtów metadanych jest przechowywanych w bazie danych.

(W dalszej części mówimy głównie o bazach klucz-wartość, dokumentach i rodzinach kolumn, bazy danych grafów mogą nie mieć tych właściwości)

2.3. Reprezentacja danych w postaci agregatów (agregatów)

W przeciwieństwie do modelu relacyjnego, który przechowuje logiczną jednostkę biznesową aplikacji w różnych fizycznych tabelach w celu normalizacji, magazyny NoSQL działają na tych jednostkach tak, jakby były holistycznymi obiektami:

Ten przykład ilustruje agregacje dla standardowego koncepcyjnego modelu relacyjnego handlu elektronicznego „Zamówienie — pozycje zamówienia — płatności — produkt”. W obu przypadkach zamówienie jest łączone z pozycjami w jeden obiekt logiczny, przy czym każda pozycja przechowuje link do produktu i niektóre jego atrybuty, na przykład nazwę (taka denormalizacja jest konieczna, aby nie żądać obiektu produktu podczas pobierania porządek - główną zasadą systemów rozproszonych jest „łączenie” obiektów). W jednym agregacie płatności są łączone z zamówieniem i stanowią integralną część przedmiotu, w drugim są umieszczane w osobnym przedmiocie. Pokazuje to główną zasadę projektowania struktury danych w bazach NoSQL – musi ona spełniać wymagania aplikacji i być maksymalnie zoptymalizowana pod kątem najczęstszych żądań.

Wielu sprzeciwi się, zauważając, że praca z dużymi, często zdenormalizowanymi obiektami jest obarczona wieloma problemami podczas próbowania dowolnych zapytań na danych, gdy zapytania nie pasują do struktury agregatów. Co jeśli używamy zamówień razem z pozycjami zamówienia i płatnościami (tak działa aplikacja), ale firma prosi nas o policzenie, ile sztuk danego produktu zostało sprzedanych w zeszłym miesiącu? W takim przypadku, zamiast skanować tabelę OrderItem (w przypadku modelu relacyjnego), będziemy musieli pobrać całe zamówienia z magazynu NoSQL, chociaż nie będziemy potrzebować wielu tych informacji. Niestety jest to kompromis, na który trzeba pójść w systemie rozproszonym: nie możemy normalizować danych jak w konwencjonalnym systemie jednoserwerowym,

Próbowałem pogrupować zalety i wady obu podejść w tabeli: