Ściąga - NoSQL
1. Relacyjne kontra NoSQL, ACID kontra BASE
Section titled “1. Relacyjne kontra NoSQL, ACID kontra BASE”Model relacyjny: tabele, związki 1:1, 1:N, M:N, klucze główne i obce, ograniczenia. Skaluje się głównie pionowo.
ACID (gwarancje transakcji w bazach relacyjnych):
- Atomicity (niepodzielność): transakcja w całości albo wcale.
- Consistency (spójność): po transakcji nie naruszone reguły integralności.
- Isolation (izolacja): transakcje nie zakłócają się nawzajem w trakcie.
- Durability (trwałość): zatwierdzone dane przetrwają awarię.
Poziomy izolacji: read uncommitted, read committed, repeatable read, serializable (od najsłabszego do najmocniejszego).
BASE (podejście baz NoSQL, kompromis wobec ACID):
- Basically Available: dostępność nie zawsze pełna.
- Soft state: stan może się zmieniać w czasie nawet bez nowych danych.
- Eventually consistent: spójność osiągana ostatecznie, po pewnym czasie.
W NoSQL spójność jest często poświęcana na rzecz szybkości i dostępności.
2. Trójkąt CAP
Section titled “2. Trójkąt CAP”W rozproszonym systemie da się spełnić tylko dwie z trzech cech:
-
Consistency: wszyscy widzą zawsze ten sam, najnowszy obraz danych.
-
Availability: każde żądanie dostaje odpowiedź (bez gwarancji aktualności).
-
Partition tolerance: system działa mimo problemów komunikacji między węzłami.
-
Bazy relacyjne (MySQL, PostgreSQL): bok CA, skalowanie pionowe.
-
Cassandra: AP, skalowanie poziome, wysoka dostępność, bez gwarancji najświeższych danych.
-
MongoDB: CP, rozproszenie z integralnością, ale przy awarii węzła część danych może być niedostępna.
3. Skalowanie: replikacja, sharding, map-reduce
Section titled “3. Skalowanie: replikacja, sharding, map-reduce”Replikacja (kopie tych samych danych na wielu węzłach, cel: niezawodność i dostępność):
- master-slave: zapis tylko przez master, on synchronizuje slave. Dobre przy przewadze odczytów.
- peer-to-peer: zapis do dowolnego węzła, brak mastera, każdy synchronizuje z innymi. Większa dostępność, zgoda na niespójność.
Sharding (fragmentowanie): różne części danych na różnych serwerach (np. podział na kraje, dni, kategorie).
- Zwiększa szybkość zapisu i odczytu.
- Nie poprawia niezawodności ani bezpieczeństwa danych (to robi replikacja).
Map-Reduce: metodologia (i framework, np. Hadoop, Spark) przetwarzania dużych zbiorów danych w klastrach. Faza map (rozdział i wstępne przetwarzanie) i faza reduce (scalenie wyników). Idea zbliżona do master-slave.
4. Typy baz NoSQL i modelowanie JSON
Section titled “4. Typy baz NoSQL i modelowanie JSON”Sześć podstawowych rodzajów:
- Key-Value: Redis, Dynamo, Riak.
- Document: MongoDB, CouchDB, Couchbase.
- Column (wide column): Cassandra, HBase, Druid.
- Graph: Neo4j, OrientDB.
- Time Series: InfluxDB, Prometheus, TimescaleDB.
Modelowanie relacji w JSON:
- Relacja 1:N w jednym pliku: zagnieżdżona tablica (array) wewnątrz dokumentu nadrzędnego.
- Relacja modelowana w dwóch plikach: drugi plik z referencją do pierwszego (np. zamówienie trzyma
klient_id). - Dokument odpowiada wierszowi w bazie relacyjnej, kolekcja odpowiada tabeli.
Agregacyjne modele danych: key-value, dokumentowe i rodzina kolumn są koncepcyjnie podobne i nazywa się je modelami zorientowanymi na agregacje. To odejście od modelu relacyjnego, w którym podstawową porcją danych jest wiersz i nie da się zagnieżdżać wierszy w wierszach. W modelach agregacyjnych jedna porcja danych (agregat) może mieć zagnieżdżoną, złożoną strukturę.
Normalizacja: w modelu relacyjnym dane rozbija się na wiele powiązanych tabel, by uniknąć redundancji (jeden klient zapisany raz, zamówienia osobno). W bazach agregacyjnych częściej idzie się w denormalizację, czyli powtórzenie danych wewnątrz jednego dokumentu dla szybkości odczytu.
Formaty danych: dane częściowo ustrukturyzowane zapisuje się w JSON, XML, YAML lub binarnie (BSON w MongoDB). JSON jest prostszy i krótszy od XML.
5. MongoDB (baza dokumentowa)
Section titled “5. MongoDB (baza dokumentowa)”Podstawy administracji i bazy:
// lista bazshow dbs// przełącz/utwórz bazę (powstaje po pierwszym zapisie)use artur// usuń bieżącą bazędb.dropDatabase()// lista kolekcjishow collections// jawne utworzenie kolekcjidb.createCollection("zam")// usuń kolekcjędb.zam.drop()Wstawianie i odczyt:
db.zam.insert({ klient: "ABC", wartosc: 100, status: "A" })// wszystkie dokumentydb.zam.find()// sformatowanedb.zam.find().pretty()// pierwszy pasującydb.zam.findOne({ klient: "ABC" })Operatory porównania w find:
// równedb.zam.find({ wartosc: 1000 })// mniejszedb.zam.find({ wartosc: { $lt: 1000 } })// mniejsze lub równedb.zam.find({ wartosc: { $lte: 1000 } })// większedb.zam.find({ wartosc: { $gt: 1000 } })// większe lub równedb.zam.find({ wartosc: { $gte: 1000 } })// różnedb.zam.find({ wartosc: { $ne: 1000 } })Projekcja (drugi argument find):
// tylko te pola (plus _id)db.zam.find({}, { klient: 1, wartosc: 1 })// ukryj _iddb.zam.find({}, { _id: 0 })Kluczowe fakty:
- Każdy dokument ma unikalne pole
_id(z podkreślnikiem). Domyślnie generowanyObjectId, ale można podać własną wartość. _idjest pokazywane domyślnie. Aby ukryć:{ _id: 0 }w projekcji.- Aktualizacja:
db.zam.update({_id:4}, {$set:{violations:3}}).
Replica Set (replikacja):
- Zestaw serwerów: jeden Primary Node, reszta Secondary Nodes.
- Po awarii Primary następuje automatyczny wybór nowego Primary spośród Secondary. Działanie jest możliwe bez ręcznej interwencji.
- Gdy padną wszystkie Secondary, dawny Primary może przejść w stan Secondary i stracić możliwość zapisu.
MongoDB w CAP to CP (integralność ważniejsza niż pełna dostępność).
6. Cassandra (rodzina kolumn)
Section titled “6. Cassandra (rodzina kolumn)”Klient: cqlsh. Każdy węzeł jest równouprawniony (architektura peer-to-peer, brak mastera).
Przestrzeń kluczy i tabele:
CREATE KEYSPACE firma WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':3};USE firma;DESC TABLES;
CREATE TABLE IF NOT EXISTS pracownik ( id int, imie text, nazwisko text, data_ur date, PRIMARY KEY (id));
INSERT INTO pracownik (id, imie, nazwisko, data_ur) VALUES (1, 'Artur', 'Nowak', '1991-12-29');SELECT * FROM pracownik;Klucz główny (primary key):
- Obowiązkowy partition key (przynajmniej jedna kolumna), opcjonalne clustering columns.
PRIMARY KEY (kraj, miasto): pierwsza kolumna to partition key (kraj), pozostałe to clustering key (miasto).- Composite partition key:
PRIMARY KEY ((country, last_name), user_email)(podwójny nawias grupuje partition key). - Każda tabela musi mieć zdefiniowany klucz główny i należy do przestrzeni kluczy.
Replikacja i spójność:
- RF (Replication Factor): liczba kopii danych. RF=1 to brak replikacji.
- CL (Consistency Level):
CL = floor(RF/2) + 1dla quorum. Dla RF=3 quorum to 2, dla RF=15 to 8. - Poziomy: QUORUM, LOCAL_QUORUM, EACH_QUORUM i inne.
ALLOW FILTERING:
SELECT * FROM tab WHERE col1 = 1 ALLOW FILTERING;- Wymagane, gdy filtrujesz po kolumnie spoza klucza partycji. Bez tego zapytanie się nie wykona.
- Powód: trzeba przejrzeć dane praktycznie we wszystkich węzłach (partycjach), co jest kosztowne.
- Wniosek: projekt struktury tabeli musi uwzględniać przyszłe zapytania.
- CQL nie obsługuje
ORwWHERE.
Filtr Blooma:
- Struktura danych, która szybko i pamięciowo oszczędnie wstępnie sprawdza, czy element należy do zbioru (np. czy email był już użyty).
- Cassandra używa go do sprawdzenia, czy plik SSTable zawiera wiersz o danym kluczu, zanim sięgnie na wolny dysk.
- Wada: dopuszcza fałszywe pozytywy (może powiedzieć, że element jest, choć go nie ma), ale nigdy fałszywych negatywów.
7. Redis (key-value, in-memory)
Section titled “7. Redis (key-value, in-memory)”Baza typu klucz-wartość, działa w pamięci operacyjnej (RAM), z opcjonalnym zapisem na dysk dla bezpieczeństwa. Serwer redis-server, klient redis-cli.
Podstawowe polecenia:
# zapis (nadpisuje istniejącą wartość)SET klucz "wartosc"# odczyt (brak klucza zwraca (nil))GET klucz# usunięcieDEL klucz# czy klucz istniejeEXISTS klucz# zapis tylko gdy klucz nie istniejeSETNX klucz wartosc# zwiększ o 1 (na wartości liczbowej)INCR licznikStruktury danych: string, list (LPUSH, RPUSH, LPOP, RPOP), set (SADD, SPOP), sorted set (ZADD), hash (HSET).
Czas życia klucza (TTL):
SET "nasza:zmienna" "tekst"# wygaśnie po 30 sekundach (klucz zostanie usunięty)EXPIRE nasza:zmienna 30# pozostały czas w sekundachTTL nasza:zmienna# pozostały czas w milisekundachPTTL nasza:zmiennaMożna też ustawić od razu: SET klucz wartosc EX 10 (10 sekund).
Transakcje:
# rozpoczęcie transakcji (kolejkowanie poleceń)MULTISET a 1INCR a# wykonanie zakolejkowanych poleceńEXEC# wycofanie transakcjiDISCARDPersystencja (persistence), dwa mechanizmy:
- RDB (Redis Database): okresowe migawki (snapshot) bazy z RAM do pliku
dump.rdb. Domyślnie włączony (np.save 900 1,save 300 10,save 60 10000). - AOF (Append Only File): zapis każdej operacji do logu (append-only), bezpieczniejszy. Domyślnie wyłączony.
- Oba można włączać i wyłączać niezależnie.
HyperLogLog (PFADD, PFCOUNT):
- Struktura do szybkiego liczenia liczby unikalnych elementów (kardynalność, count-distinct) przy małym zużyciu pamięci.
- Wynik przybliżony, błąd standardowy poniżej 0.81 procenta. Dla 20000 unikalnych elementów wynik mieści się mniej więcej w przedziale plus minus 162.
8. InfluxDB (szeregi czasowe)
Section titled “8. InfluxDB (szeregi czasowe)”Baza szeregów czasowych (time series). Wersja Core (OSS) i Enterprise.
Format danych: line protocol, składa się z:
- table (measurement): napis identyfikujący grupę pomiarów, odpowiednik tabeli lub kolekcji.
- tag set: pary klucz-wartość rozdzielone przecinkami, bez cudzysłowów (indeksowane metadane).
- field set: pary klucz-wartość z właściwymi wartościami pomiaru. Typy: strings (w cudzysłowie), floats, integers, unsigned integers, booleans.
- timestamp: znacznik czasu w formacie Unix timestamp, dokładność do 1 nanosekundy.
Unix timestamp: liczba sekund od 1 stycznia 1970 (RFC3339). 32-bitowy wariant wyczerpie się 19 stycznia 2038 (problem roku 2038).
Pułapki egzaminacyjne (szybkie odpowiedzi)
Section titled “Pułapki egzaminacyjne (szybkie odpowiedzi)”MongoDB:
use bazaprzełącza na bazę i tworzy ją po pierwszym zapisie.- Listowanie baz:
show dbs. Kolekcji:show collections. - Unikalny klucz dokumentu: pole
_id. Można podać własną wartość. - Ukrycie identyfikatorów w wyniku:
find({}, {_id:0}). find({cena:{$ne:20}})zwraca dokumenty z ceną różną od 20.- Dokument odpowiada wierszowi tabeli relacyjnej.
- Po utracie Primary działanie jest możliwe (automatyczny wybór nowego Primary).
- Błędny indeks:
createIndex({klient:1, unique:true})(opcjauniquenależy do drugiego argumentu). - MongoDB w CAP to CP.
Cassandra:
- RF=15, quorum CL = floor(15/2)+1 = 8.
- W
PRIMARY KEY (kategoria, punkty)druga kolumna to clustering key. - Filtrowanie po kolumnie spoza klucza partycji wymaga
ALLOW FILTERING. ALLOW FILTERINGjest kosztowne, bo trzeba przejrzeć wszystkie węzły.- Każdy węzeł jest równouprawniony (peer-to-peer).
- CQL nie obsługuje
ORwWHERE. - Każda tabela musi mieć klucz główny.
- Migracja 4 tabel po 10, 20, 30, 40 rekordów do grafu (Neo4j): 100 węzłów i 4 etykiety.
Redis:
EXPIRE zmienna 30: klucz usuwany po 30 sekundach.- Klucz z czasem życia:
SET zm wart EX 10. - Błędne polecenie:
SET mykey(brak wartości). GETna nieistniejącym kluczu zwraca(nil).- Rozpoczęcie transakcji:
MULTI. Wykonanie:EXEC. Wycofanie:DISCARD. - Redis działa w RAM, z opcjonalnym zapisem na dysk (RDB lub AOF), konfiguracja w
redis.conf. - RDB i AOF to mechanizmy persystencji Redis.
- Wartości to napisy:
SET key 2+4zapisze tekst2+4.SET key apoSET key 1iINCRda3. SET klucz "moje dane"poprawne (spacja w cudzysłowie),SET klucz moje danebłędne.- HyperLogLog: błąd standardowy poniżej 0.81 procenta.
Ogólne:
- Replikacja poprawia niezawodność przechowywania danych.
- Sharding zwiększa szybkość, ale nie poprawia niezawodności i bezpieczeństwa.
- Map-reduce to metodologia przetwarzania dużych zbiorów w środowisku rozproszonym.
- Istota NoSQL: spójność bywa mniej istotna niż szybkość działania.
- W modelu relacyjnym każda kolumna zawiera dane tego samego typu.
- Relacja 1:N w jednym pliku JSON: zagnieżdżona tablica (array).
9. Neo4j (baza grafowa, Cypher)
Section titled “9. Neo4j (baza grafowa, Cypher)”Baza grafowa: węzły (nodes) i relacje (krawędzie). Interfejs przeglądarkowy pod http://localhost:7474. Polecenia systemowe wydaje się z dwukropkiem (:help, :sysinfo, :play cypher).
Zapis w Cypherze:
(nawiasy okrągłe)to węzły.[nawiasy kwadratowe]to relacje.{nawiasy klamrowe}to właściwości.- Etykieta po dwukropku grupuje węzły, np.
(p:Person). - Kierunek relacji oznaczają znaki mniejszości i większości.
// tworzenie węzłówCREATE (friend:Person {name: 'Jennifer'});CREATE (friend:Person {name: 'Mark'});
// tworzenie relacji między istniejącymi węzłamiMATCH (jennifer:Person {name: 'Jennifer'})MATCH (mark:Person {name: 'Mark'})CREATE (jennifer)-[rel:IS_FRIENDS_WITH]->(mark);
// MATCH to odpowiednik SQL-owego SELECT, szuka wzorca// wszystkie osoby (zmienna p wymagana do RETURN)MATCH (p:Person) RETURN p;MATCH (p:Person {name: 'Tom Hanks'}) RETURN p;// wszystkie daneMATCH (n) RETURN n;// odpowiednik SELECT * FROM MovieMATCH (m:Movie) RETURN m;
// filtr WHERE i inne klauzule: WHERE, ORDER BY, SKIP, LIMIT, ANDMATCH (p:Person) WHERE p.unitPrice > 10 RETURN p;
// dodanie/zmiana właściwościMATCH (p:Person {name: 'Jennifer'}) SET p.birthdate = date('1980-01-01');
// usunięcie właściwości// lub REMOVE n.data_urMATCH (n {name: 'Piotr'}) SET n.data_ur = null;
// usunięcie relacjiMATCH (n {name: 'B'})-[r:XYZ]->() DELETE r;
// usunięcie węzła wraz z relacjamiMATCH (n) DETACH DELETE n;Kierunki relacji: -[r]-> w prawo, <-[r]- w lewo, -[r]- bez kierunku. Nie da się postawić strzałek po obu stronach (<-[r]-> jest błędne).
Fakty: węzły mogą (nie muszą) mieć właściwości i etykiety. Import z CSV pozwala wczytać zarówno węzły, jak i relacje. Przy migracji z bazy relacyjnej liczba węzłów to suma rekordów, a liczba etykiet to liczba tabel (4 tabele po 10, 20, 30, 40 rekordów dają 100 węzłów i 4 etykiety).