Programovanie

Analýza veľkých dát s Neo4j a Java, 1. časť

Relačné databázy dominujú v správe dát po celé desaťročia, ale nedávno stratili pôdu pod noxQL alternatívami. Aj keď dátové úložiská NoSQL nie sú vhodné pre všetky prípady použitia, vo všeobecnosti sú lepšie veľké dáta, čo je skratka pre systémy, ktoré spracúvajú obrovské objemy dát. Pre veľké dáta sa používajú štyri typy dátových úložísk:

  • Úložiská kľúčov a hodnôt, ako sú Memcached a Redis
  • Dokumentovo orientované databázy ako MongoDB, CouchDB a DynamoDB
  • Stĺpovo orientované dátové sklady ako Cassandra a HBase
  • Grafické databázy ako Neo4j a OrientDB

Tento výukový program predstavuje Neo4j, čo je databáza grafov, ktorá sa používa na interakciu s programom vysoko súvisiace údaje. Zatiaľ čo relačné databázy sú dobré pri riadení vzťahov medzi dáta, databázy grafov sú lepšie v správe n-tá stupňa vzťahov. Ako príklad si môžete vziať sociálnu sieť, kde chcete analyzovať vzorce týkajúce sa priateľov, priateľov priateľov atď. Databáza grafov by uľahčila odpoveď na otázku typu: „Čo je to päť filmov obľúbených na mojej sociálnej sieti, ktoré som ešte nevidel?“ Takéto otázky sú bežné pre odporúčací softvér a databázy grafov sú ideálne na ich riešenie. Databázy grafov navyše dobre reprezentujú hierarchické údaje, ako sú napríklad kontroly prístupu, katalógy produktov, databázy filmov alebo dokonca topológie sietí a organizačné schémy. Ak máte objekty s viacerými vzťahmi, rýchlo zistíte, že databázy grafov ponúkajú elegantnú objektovo orientovanú paradigmu pre správu týchto objektov.

Prípad databáz grafov

Ako naznačuje názov, databázy grafov dobre reprezentujú grafy údajov. To je užitočné najmä pre sociálny softvér, kde vždy, keď sa s niekým spojíte, je medzi vami definovaný vzťah. Pravdepodobne pri poslednom hľadaní zamestnania ste si vybrali niekoľko spoločností, ktoré vás zaujímali, a potom ste vo svojich sociálnych sieťach vyhľadali prepojenia. Aj keď možno nepoznáte nikoho, kto pracuje pre niektorú z týchto spoločností, niekto vo vašej sociálnej sieti to pravdepodobne vie. Takéto riešenie problému je ľahké pri jednom alebo dvoch stupňoch odlúčenia (váš priateľ alebo priateľ), ale čo sa stane, keď začnete s rozširovaním vyhľadávania po celej sieti?

Aleksa Vukotic a Nicki Watt vo svojej knihe Neo4j In Action skúmajú rozdiely medzi relačnými databázami a databázami grafov na riešenie problémov sociálnych sietí. Z nasledujúcich príkladov čerpám z ich práce, aby som vám ukázal, prečo sa databázy grafov stávajú čoraz populárnejšou alternatívou k relačným databázam.

Modelovanie zložitých vzťahov: Neo4j vs MySQL

Z pohľadu počítačovej vedy, keď uvažujeme o modelovaní vzťahov medzi používateľmi v sociálnej sieti, môžeme nakresliť graf, ako je ten na obrázku 1.

Steven Haines

Používateľ má IS_FRIEND_OF vzťahy s ostatnými používateľmi a títo používatelia majú IS_FRIEND_OF vzťahy s ostatnými používateľmi atď. Obrázok 2 ukazuje, ako by sme to reprezentovali v relačnej databáze.

Steven Haines

The UŽÍVATEĽ tabuľka má vzťah typu jedna k mnohým s USER_FRIEND tabuľka, ktorá modeluje „priateľský“ vzťah medzi dvoma používateľmi. Teraz, keď sme modelovali vzťahy, ako by sme dotazovali naše údaje? Vukotic a Watt merali výkonnosť dotazu na spočítanie počtu rôznych priateľov, ktorí vyšli do hĺbky piatich úrovní (priatelia priateľov priateľov priateľov priateľov). V relačnej databáze by dotazy vyzerali takto:

 # Hĺbka 1 vyberte počet (zreteľne uf. *) Od user_friend uf kde uf.user_1 =? # Hĺbka 2 vyberte počet (odlišný uf2. *) Z user_friend uf1 vnútorné spojenie user_friend uf2 na uf1.user_1 = uf2.user_2 kde uf1.user_1 =? # Hĺbka 3 vyberte počet (odlišný uf3. *) Od t_user_friend uf1 vnútorné spojenie t_user_friend uf2 na uf1.user_1 = uf2.user_2 vnútorné spojenie t_user_friend uf3 na uf2.user_1 = uf3.user_2 kde uf1.user_1 =? # A tak ďalej... 

Čo je zaujímavé na týchto dotazoch, je to, že zakaždým, keď vyjdeme o jednu úroveň vyššie, musíme sa k nim pripojiť USER_FRIEND stôl sám so sebou. Tabuľka 1 ukazuje, čo našli vedci Vukotic a Watt, keď vložili 1 000 používateľov s približne 50 vzťahmi (50 000 vzťahov) a spustili dotazy.

Tabuľka 1. Čas odozvy na dopyt MySQL pre rôzne hĺbky vzťahov

DepthExecution time (seconds) Count count

20.028~900
30.213~999
410.273~999
592.613~999

MySQL odvádza skvelú prácu pri pripájaní údajov až o tri úrovne ďalej, ale potom sa výkon rýchlo zníži. Dôvod je ten, že zakaždým USER_FRIEND Ak je tabuľka spojená sama so sebou, musí MySQL vypočítať kartézsky produkt tabuľky, aj keď väčšina údajov bude vyhodená. Napríklad pri vykonávaní tohto spojenia päťkrát bude mať karteziánsky súčin hodnotu 50 000 ^ 5 riadkov alebo 102,4 * 10 ^ 21 riadkov. To je mrhanie, keď nás zaujíma iba 1 000 z nich!

Ďalej sa Vukotic a Watt pokúsili vykonať rovnaký typ dotazov proti Neo4j. Tieto úplne odlišné výsledky sú uvedené v tabuľke 2.

Tabuľka 2. Čas odozvy Neo4j pre rôzne hĺbky vzťahov

DepthExecution time (seconds) Count count

20.04~900
30.06~999
40.07~999
50.07~999

Získanie z týchto porovnaní popráv je nie že Neo4j je lepší ako MySQL. Pri prechádzaní týmito typmi vzťahov je výkon Neo4j skôr závislý od počtu získaných záznamov, zatiaľ čo výkon MySQL závisí od počtu záznamov v USER_FRIEND stôl. S rastúcim počtom vzťahov sa teda rovnako zvýšia časy odozvy pre dotazy MySQL, zatiaľ čo odozvy pre dotazy Neo4j zostanú rovnaké. Je to preto, že doba odozvy Neo4j závisí od počtu vzťahov pre konkrétny dopyt, a nie od celkového počtu vzťahov.

Škálovanie Neo4j pre veľké dáta

Vukotic a Watt rozšírili tento myšlienkový projekt o ďalší krok ďalej a vytvorili tak milión používateľov s 50 miliónmi vzťahov medzi nimi. Tabuľka 3 zobrazuje výsledky pre túto množinu údajov.

Tabuľka 3. Čas odozvy Neo4j na 50 miliónov vzťahov

DepthExecution time (seconds) Count count

20.01~2,500
30.168~110,000
41.359~600,000
52.132~800,000

Netreba dodávať, že vďačím Aleksa Vukotic a Nicki Watt a dôrazne odporúčam skontrolovať ich prácu. Všetky testy v tejto časti som vyňal z prvej kapitoly ich knihy, Neo4j v akcii.

Začíname s Neo4j

Videli ste, že Neo4j je schopný veľmi rýchlo vykonať obrovské množstvo vysoko súvisiacich údajov a nie je pochýb o tom, že je vhodný pre niektoré druhy problémov ako MySQL (alebo akákoľvek relačná databáza). Ak chcete pochopiť viac o tom, ako Neo4j funguje, najjednoduchší spôsob je komunikovať s ním prostredníctvom webovej konzoly.

Začnite stiahnutím Neo4j. V tomto článku budete chcieť vydanie komunity, ktoré je v tomto článku vo verzii 3.2.3.

  • Na počítači Mac si stiahnite súbor DMG a nainštalujte ho ako ktorúkoľvek inú aplikáciu.
  • V systéme Windows si buď stiahnite EXE a prejdite sprievodcom inštaláciou, alebo stiahnite súbor ZIP a dekomprimujte ho na pevný disk.
  • V systéme Linux si stiahnite súbor TAR a dekomprimujte ho na pevnom disku.
  • Prípadne použite Dockerov obraz na ľubovoľnom operačnom systéme.

Po nainštalovaní Neo4j ho spustite a otvorte okno prehliadača na nasledujúcej adrese URL:

//127.0.0.1:7474/browser/

Prihláste sa s predvoleným používateľským menom neo4j a predvolené heslo pre neo4j. Mali by ste vidieť obrazovku podobnú obrázku 3.

Steven Haines

Uzly a vzťahy v Neo4j

Neo4j je navrhnutý okolo konceptu uzlov a vzťahov:

  • A uzol predstavuje vec, ako napríklad používateľ, film alebo kniha.
  • Uzol obsahuje množinu páry kľúč / hodnota, ako je meno, titul alebo vydavateľ.
  • Uzol štítok definuje, o aký typ veci ide - opäť Používateľ, Film alebo Kniha.
  • Vzťahy definujú asociácie medzi uzlami a sú konkrétneho typu.

Ako príklad by sme mohli definovať znakové uzly ako Iron Man a Captain America; definovať uzol filmu s názvom „Avengers“; a potom definujte APPEARS_IN vzťah medzi Iron Manom ​​a Avengers a Captain America a Avengers. To všetko je znázornené na obrázku 4.

Steven Haines

Obrázok 4 zobrazuje tri uzly (dva uzly znakov a jeden uzol filmu) a dva vzťahy (oba typu APPEARS_IN).

Modelovanie a dopytovanie uzlov a vzťahov

Podobne ako v relačnej databáze používa štruktúrovaný dotazovací jazyk (SQL) na interakciu s údajmi, Neo4j používa Cypher dotazovací jazyk na interakciu s uzlami a vzťahmi.

Použime program Cypher na vytvorenie jednoduchého znázornenia rodiny. V hornej časti webového rozhrania vyhľadajte znak dolára. Toto označuje pole, ktoré vám umožňuje vykonávať Cypherove dotazy priamo proti Neo4j. Do tohto poľa zadajte nasledujúci dopyt Cypher (ako príklad uvádzam svoju rodinu, ak chcete, môžete prípadne zmeniť podrobnosti a vymodelovať tak svoju vlastnú rodinu):

VYTVORIŤ (osoba: Osoba {meno: "Steven", vek: 45}) NÁVRATNÁ osoba

Výsledok je uvedený na obrázku 5.

Steven Haines

Na obrázku 5 môžete vidieť nový uzol so štítkom Osoba a menom Steven. Ak umiestnite kurzor myši na uzol vo vašej webovej konzole, uvidíte jeho vlastnosti v dolnej časti. V tomto prípade sú to vlastnosti ID: 19, meno: Steven a vek: 45. Poďme si rozdeliť Cypherov dotaz:

  • VYTVORIŤ: VYTVORIŤ kľúčové slovo sa používa na vytvorenie uzlov a vzťahov. V tomto prípade mu odovzdáme jediný argument, ktorým je a Osoba uzavreté v zátvorkách, takže to má vytvoriť jeden uzol.
  • (osoba: Osoba {...}): Malé písmená “osoba„je premenné meno, pomocou ktorého môžeme získať prístup k vytváranej osobe, zatiaľ čo k hlavnému kapitálu“Osoba„je štítok. Upozorňujeme, že dvojbodka oddeľuje názov premennej od štítka.
  • {name: "Steven, vek: 45}: Toto sú vlastnosti kľúča / hodnoty, ktoré definujeme pre uzol, ktorý vytvárame. Neo4j nevyžaduje, aby ste pred vytvorením uzlov definovali schému a každý uzol môže mať jedinečnú sadu prvkov. (Väčšinou definujete uzly s rovnakým štítkom, aby mali rovnaké vlastnosti, ale nie je to potrebné.)
  • NÁVRATNÁ osoba: Po vytvorení uzla požiadame Neo4j, aby nám ho vrátil späť. Z tohto dôvodu sme videli uzol, ktorý sa objavil v používateľskom rozhraní.

The VYTVORIŤ príkaz (v ktorom sa nerozlišujú malé a veľké písmená) sa používa na vytváranie uzlov a dá sa čítať nasledovne: vytvorte nový uzol s menovkou Person, ktorý obsahuje vlastnosti mena a veku; priraďte ju k premennej osoba a vráťte ju späť volajúcemu.

Dopytovanie pomocou jazyka Cypher Query Language

Ďalej si chceme vyskúšať nejaké dotazovanie s Cypherom. Najskôr budeme musieť vytvoriť niekoľko ďalších ľudí, aby sme mohli definovať vzťahy medzi nimi.

 CREATE (osoba: Osoba {meno: "Michael", vek: 16}) NÁVRATNÁ osoba CREATE (osoba: Osoba {meno: "Rebecca", vek: 7}) NÁVRATNÁ osoba CREATE (osoba: Osoba {meno: "Linda"}) ) NÁVRATNÁ osoba 

Po vytvorení svojich štyroch ľudí môžete kliknúť na ikonu Osoba tlačidlo pod Štítky uzlov (viditeľné, ak kliknete na ikonu databázy v ľavom hornom rohu webovej stránky) alebo vykonáte nasledujúci dotaz Cypher:

ZÁPAS (osoba: Osoba) NÁVRATNÁ osoba

Cypher používa ZÁPAS kľúčové slovo na vyhľadanie vecí v Neo4j. V tomto príklade žiadame Cypher, aby priradil všetky uzly, ktoré majú štítok Person, a priradil ich k osoba premenná a vráti hodnotu, ktorá je s touto premennou spojená. Vo výsledku by ste mali vidieť štyri uzly, ktoré ste vytvorili. Ak umiestnite kurzor myši na každý uzol vo svojej webovej konzole, zobrazia sa vlastnosti jednotlivých osôb. (Môžete si všimnúť, že som vylúčil vek mojej manželky z jej uzla, čo dokazuje, že vlastnosti nemusia byť konzistentné naprieč uzlami, dokonca ani s rovnakým štítkom. Tiež nie som taký hlupák, aby som zverejnil vek mojej ženy.)

Môžeme to predĺžiť ZÁPAS príklad trochu ďalej pridaním podmienok do uzlov, ktoré chceme vrátiť. Napríklad, ak by sme chceli iba uzol „Steven“, mohli by sme ho načítať zhodou vo vlastnosti name:

ZÁPAS (osoba: Osoba {meno: „Steven“}) NÁVRATNÁ osoba

Alebo, ak by sme chceli vrátiť všetky deti, mohli by sme požiadať všetkých ľudí vo veku do 18 rokov:

ZÁPAS (osoba: Osoba) KDE person.age <18 NÁVRATNÁ osoba

V tomto príklade sme pridali znak KDE klauzula dotazu na zúženie našich výsledkov. KDE funguje veľmi podobne ako jeho ekvivalent SQL: ZÁPAS (osoba: osoba) vyhľadá všetky uzly so štítkom Osoba a potom KDE klauzula filtruje hodnoty z množiny výsledkov.

Modelovanie smeru vo vzťahoch

Máme štyri uzly, takže vytvorme nejaké vzťahy. Najskôr si vytvorme IS_MARRIED_TO vzťah medzi Stevenom a Lindou:

ZÁPAS (steven: Osoba {meno: "Steven"}), (linda: Osoba {meno: "Linda"}) CREATE (steven) - [: IS_MARRIED_TO] -> (linda) návrat steven, linda

V tomto príklade spojíme dva uzly Persona označené ako Steven a Linda a vytvoríme vzťah typu IS_MARRIED_TO od Stevena po Lindu. Formát na vytvorenie vzťahu je nasledovný:

(node1) - [relationshipVariable: RELATIONSHIP_TYPE -> (node2)
$config[zx-auto] not found$config[zx-overlay] not found