piątek, 4 kwietnia 2014

neo4j in practice part 1 (neo4j basic)

Neo4j przedstawiciel baz grafowych.
W tym poście pokaże jak możemy wykorzystać bazę grafową oraz jej mocne cechy. Wprowadzę Cię w  świat grafów na podstawie dwóch projektów wymyślonych przez ze mnie na potrzeby tego posta :) :



1. Zarządzanie projektami informatycznymi (ocenianie i wyciąganie wniosków, dobór programistów do zespołów, minimalizacja ryzyka)






























2. Obliczenia najkrótszej możliwej ścieżki z perspektywy hipotetycznego podróżnika tj :
 - wyznaczanie najtańszej trasy
 - wyznaczenie najszybszej trasy
 - wyznaczenie najkrótszej trasy.




Zrobimy to stosując najnowszego spring 4.0.3 w połączeniu z java 8 oraz neo4j i spring data. Interfejs dostępowy będzie stanowił REST (+ Hateoas)

Ponieważ jest to projekt prototypowy użyjemy też Spring Boot'a, o którym wspominałem w poprzednich postach. Do budowania całości zaprzęgniemy Gradle.

TIP : Diagramy i rysunki wykonuje na kartce papieru w sposób mniej więcej taki jak wyżej. Dlaczego ? Trzeba dbać o architekturę rozwiązania równie bardzo jak o i jego implementacje. Zadaj sobie pytanie jak bardzo implementacja danego rozwiązania ma wspólnego z pięknymi diagramami zrobionymi w Enterprise Architect ? :)  - Często wcale...

Bazy grafowe :
- zawierają węzły i relacje (nodes and relationships)
- węzły zawierają wartości para-klucz (key-value pairs)
- relacje są nazwane i ukierunkowane, zawsze mają też początek i koniec. Nie istnieją wiszące relacje.
- relacje również mogą zawierać właściwości

Cechy : 
  - wydajność 
    Ogromny skok wydajności w stosunku do relacyjnych baz danych. Ilość  joinów w połączeniu ze wzrostem zbiorów danych powoduje drastyczny spadek wydajności zapytań. W neo4j relacja ta jest względnie stała. Czas wykonania zapytania jest proporcjonalny do części grafu w którym nastąpi traversing, niż do ogólnego rozmiaru całego grafu. To bardzo dobra wiadomość.

W miarę rozrastania się relacyjnych baz danych rośnie liczba połączeń między tabelami, złożoność modelu biznesowego sprawia, że relację stają się mniej jednolite. Rośnie ilość logiki która wymaga sprawdzeń czy wartość nie jest null'em itd.

- joiny - spowalniają wykonywanie zapytań

- klucze obce jako constraints wymagają większego narzutu na utrzymalność oraz rozwój struktury bazy

- table często zawierają wartości puste np JPA Single_Table Strategy - często będzie wymagana dodatkowa kontrola w kodzie.

- rekustywne zapytania są zabójstwem dla relacyjnych baz danych. Indeksacja nic tu nie pomoże

  - elastyczność
 Możemy manipulować schematem danych w dowolny sposób. Tworzyć nowe rodzaje relacji, podgrafy, węzły bez naruszania istniejących zapytań czy funkcjonalności aplikacji. Ta własność pozytywnie odbije się na pracę programistów czy projektantów dając im większą elastyczność - wprost nieograniczoną w modelowaniu danych. Z punktu widzenia biznesu to również wielka zaleta ponieważ wymagania biznesowe często się zmieniają (agile)
  - sprawność
Neo4j posiada fajne narzędzia do zarządzania bazą. Wizualizację, wykresy, query executor itd. Mamy możliwość  podłączenia ad-hoc REST API. Kalkulator za pomocą którego możemy dobrać wymagania sprzętowe do naszych potrzeb oraz wiele innych cennych rzeczy.
 
Relacyjne bazy danych a Neoj4 (podsumowując powyższe):
W pewnych przypadkach 'join' może wprowadzać przypadkową złożoności i komplikować dane biznesowe.
Poza złączenia są to kosztowne operacje.
Klucze obce powodują dodatkowy narzut i zwiększają koszt utrzymania struktury.
Puste kolumny w bazie wymagają i tak weryfikacji w aplikacji.

Mamy nasŧępujący  już chyba książkowy problem:
Aby zasymulować taką  sytuacje w relacyjnych bazach potrzebuję dwie tabelki.
Pierwsza zawiera nazwiska i dane osoby , a druga relację koleżeństwa pomiędzy osobami.
Szukam przyjaciół danej osoby. W SQL to też prosta operacja wystarczy jeden join.

Gorzej już kiedy pytam kto jest przyjacielem moich przyjaciół, albo chcemy odwrócić relację wyszukiwania. Istnieją operacją potrafiące uprościć zapytanie np CONNECT BY  (Oracle) - ale i tak  nie potrafiące zmniejszyć złożoności obliczeniowej.

Czy w sql jest możliwe w ogóle wydajne znajdowanie takich relacji - nie. Gorzej będzie jeszcze jak będziemy bardziej drążyć w dół.
Każda kolejna relacja koleżeństwa to kolejny join w bazie.

Idąc w głąb refleksyjnie mamy problem w standardowych bazach danych. Taka baza po prostu nie wytrzyma. W końcu przestanie odpowiadać.

źródło : Neo4j in action 

 


Neo4j:
Depth     Execution time (seconds) for 1 million users     Count result
2                                 0.01                                                      ~2500
3                                 0.168                                               ~110,000
4                                 1.359                                               ~600,000
5                                 2.132                                               ~800,000
Mysql : ---------------------------------------------------------------------------------------------
2                                0.016                                                      ~2500
3                                30.267                                               ~125,000
4                               1543.505                                             ~600,000
5                               Not finished                                               —


Powyższą tabelka pochodzi z książki Neo4j in action. Obrazuje porównanie wydajności bazy relacyjnej i neo4j w przypadku modelowania problemu : friends-of-friends

W Neo4j wydajność maleje liniowo wraz ze ilością danych i jest przewidywalna do kilku poziomów głębokości. Wszystko to dzięki traversingowi, który pozwala odwiedzać tylko te relacje i wierzchołki które nas interesują, a nie jak w przypadku baz relacyjnych join'y tworzą Cartesian relations  zanim przefiltruje nietrafne wyniki. Więc zbiór rekordów rośnie w zastraszającym tempie.
Jeśli chcesz dowiedzieć się dokładnie jak to wygląda polecam wyżej wspominaną książkę Neo4j in Action.

Neo4j - Teoria

Węzły zawierają własności (klucz-wartość ) - myśl o nich jak o dokumentach
Relację tworzą połączenia pomiędzy węzłami. Zawsze są ukierunkowane i mogą zawierać etykietę.

graphdb-nodes-overview.svg

Cypher - język zapytań do wykonywania operacji na grafach. Został zaprojektowany by w prosty sposób pobierać informację zawarte w grafie. Jak większość języków zapytać Cypher składa się z klauzul.

Najprostsze zapytanie ma strukturę START -  MATCH - RETURN

START - określa jeden lub więcej początkowych węzłów lub relacji. Punkt startowy jest określany za pomocą indeksu, rzadziej za pomocą indentyfikatorów węzłów lub relacji.

MATCH
 - wzraca wszystkie podkategorie dla kategorii o nazwie 'books'
  Do realizacji relacji używamy (--> i <--) gdzie strzałka oznacza kierunek relacji.
RETURN - określa co ma być wynikiem operacji
CREATE - tworzy węzły lub relację
DELETE - usuwa węzły , relację bądź właściwości
WHERE - dostarcza kryteria do filtrowania lub tworzenia zapytań
SET - ustala właściwości
FOREACH - wykonuje  modyfikację elementów na liście
UNION - łączy wyniki pochodzące z dwóch lub więcej zapytań
WITH - pozwala na rozdzielenie łańcucha zapytania na fragmenty. Analogiczne do pipe w Unix.
Traversing - jest to operacja przeglądania zbioru węzłów grafu poprzez przechodzenie pomiędzy węzłami, które to połączone są danymi relacjami.
Jest on podstawową operacją pobierania danych z grafu. Ważne jest to, że pobieramy zestaw danych które potrzebujemy, bez potrzeby kosztowych operacji grupowania danych (np join , co miało miejsce w bazach relacyjnych)
Neo4j dostarcza nam bogate API do operacji traversingu. Dodatkowo mamy REST API oraz cypher poprzez, które możemy modelować tego typu zapytania.

Aby wykonać traversing musimy wyznaczyć węzeł startowy, wyznaczyć relację które nas interesują i wydobyć kolekcję węzłów jako wynik. Algorytm będzie przesuwał się od początkowego węzła do następnego po krawędzi węzła. Kiedy reguła osiągnie punkt 'stop' traversing się zakończy. Możemy też zdefiniować  na jakiej głębokości  algorytm ma się zatrzymać.

Traversing jest siłą przeglądania danych w Neo4j.

TIP : Neo4j jest w pełni transakcyjna ACID .
TIP : Chcą wycofać dane po wykonanym teście wystarczy dać @Transaction :)
TIP : Używając Neo4j projektujesz bazę jak na tablicy czy kartce. Nie potrzeba żadnej filozofii.

To jest wstęp do Noe4j.
W następnych postach zamodelujemy i  zaimplementujemy  funkcjonalność omówioną na początku posta. Przejdziemy przez model danych, bazy, wybór odpowiedniej strategii dla bazy Neo4j,  konfigurację Spring Boot, zaprojektowanie API REST i przetestowanie całości.

cdn

Brak komentarzy:

Prześlij komentarz