Prvi vtisi o Amazon Neptunu

Pozdrav, prebivalci Khabrovsk. V pričakovanju začetka tečaja "AWS za razvijalce" Pripravili smo prevod zanimivega gradiva.

Prvi vtisi o Amazon Neptunu

V mnogih primerih uporabe, ki so nam všeč bakdataKot vidimo na spletnih mestih naših strank, so ustrezne informacije skrite v povezavah med entitetami, na primer pri analizi odnosov med uporabniki, odvisnosti med elementi ali povezav med senzorji. Takšni primeri uporabe so običajno modelirani na grafu. V začetku tega leta je Amazon izdal svojo novo podatkovno bazo grafov Neptun. V tej objavi želimo deliti svoje prve ideje, dobre prakse in kaj lahko sčasoma izboljšamo.

Zakaj smo potrebovali Amazon Neptune

Podatkovne baze Graph obljubljajo, da bodo bolje ravnale z zelo povezanimi nizi podatkov kot njihovi relacijski ekvivalenti. V takšnih nizih podatkov so ustrezne informacije običajno shranjene v odnosih med objekti. Za testiranje Neptuna smo uporabili osupljiv projekt odprtih podatkov MusicBrainz. MusicBrainz zbira vse vrste glasbenih metapodatkov, ki si jih lahko zamislite, kot so informacije o izvajalcih, pesmih, izdajah albumov ali koncertih, pa tudi o tem, s kom je izvajalec za skladbo sodeloval ali kdaj je bil album izdan v kateri državi. MusicBrainz lahko razumemo kot ogromno mrežo subjektov, ki so nekako povezani z glasbeno industrijo.

Nabor podatkov MusicBrainz je na voljo kot izpis CSV relacijske zbirke podatkov. Odlagališče skupaj vsebuje približno 93 milijonov vrstic v 157 tabelah. Medtem ko nekatere od teh tabel vsebujejo osnovne podatke, kot so izvajalci, dogodki, posnetki, izdaje ali skladbe, druge povezovalne tabele — shranjujejo razmerja med izvajalci in posnetki, drugimi izvajalci ali izdajami itd... Prikazujejo strukturo grafa nabora podatkov. Pri pretvorbi nabora podatkov v trojčke RDF smo pridobili približno 500 milijonov primerkov.

Na podlagi izkušenj in vtisov projektnih partnerjev, s katerimi sodelujemo, predstavljamo okolje, v katerem se ta baza znanja uporablja za pridobivanje novih informacij. Poleg tega pričakujemo, da se bo redno posodabljal, na primer z dodajanjem novih izdaj ali posodabljanjem članov skupine.

prilagoditev

Kot je bilo pričakovano, je namestitev Amazon Neptune preprosta. Je precej podrobna dokumentirano. Bazo podatkov grafov lahko zaženete v samo nekaj klikih. Ko pa gre za podrobnejšo konfiguracijo, potrebne informacije težko najti. Zato želimo pokazati na en konfiguracijski parameter.

Prvi vtisi o Amazon Neptunu
Posnetek zaslona konfiguracije za skupine parametrov

Amazon pravi, da se Neptune osredotoča na transakcijske delovne obremenitve z nizko zakasnitvijo, zato je privzeta časovna omejitev zahteve 120 sekund. Vendar smo preizkusili veliko primerov analitične uporabe, v katerih smo redno dosegali to mejo. To časovno omejitev lahko spremenite tako, da ustvarite novo skupino parametrov za Neptune in nastavite neptune_query_timeout ustrezno omejitev.

Nalaganje podatkov

Spodaj bomo podrobno obravnavali, kako smo naložili podatke MusicBrainz v Neptune.

Odnosi v treh

Najprej smo pretvorili podatke MusicBrainz v trojčke RDF. Zato smo za vsako tabelo definirali predlogo, ki določa, kako je vsak stolpec predstavljen v trojčku. V tem primeru je vsaka vrstica iz tabele izvajalcev preslikana v dvanajst trojčkov RDF.

<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/gid> "${gid}"^^<http://www.w3.org/2001/XMLSchema#string> .
 
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/name> "${name}"^^<http://www.w3.org/2001/XMLSchema#string> .
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/sort-name> "${sort_name}"^^<http://www.w3.org/2001/XMLSchema#string> .
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/begin-date> "${begin_date_year}-${begin_date_month}-${begin_date_day}"^^xsd:<http://www.w3.org/2001/XMLSchema#date> .
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/end-date> "${end_date_year}-${end_date_month}-${end_date_day}"^^xsd:<http://www.w3.org/2001/XMLSchema#date> .
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/type> <http://musicbrainz.foo/artist-type/${type}> .
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/area> <http://musicbrainz.foo/area/${area}> .
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/gender> <http://musicbrainz.foo/gender/${gender}> .
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/comment> "${comment}"^^<http://www.w3.org/2001/XMLSchema#string> .
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/edits-pending> "${edits_pending}"^^<http://www.w3.org/2001/XMLSchema#int> .
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/last-updated> "${last_updated}"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
 
<http://musicbrainz.foo/artist/${id}> <http://musicbrainz.foo/ended> "${ended}"^^<http://www.w3.org/2001/XMLSchema#boolean> .

nalaganje v velikem obsegu

Predlagani način za nalaganje velikih količin podatkov v Neptune je postopek množičnega nalaganja prek S3. Ko naložite svoje trojne datoteke v S3, začnete nalaganje z zahtevo POST. V našem primeru je za 24 milijonov trojčkov trajalo približno 500 ur. Pričakovali smo, da bo hitrejši.

curl -X POST -H 'Content-Type: application/json' http://your-neptune-cluster:8182/loader -d '{
 
 
 "source" : "s3://your-s3-bucket",
 
 "format" : "ntriples",
 
 "iamRoleArn" : "arn:aws:iam::your-iam-user:role/NeptuneLoadFromS3",
 
 "region" : "eu-west-1",
 
 "failOnError" : "FALSE"
 
}'

Da bi se izognili temu dolgotrajnemu procesu vsakič, ko zaženemo Neptune, smo se odločili obnoviti primerek iz posnetka, v katerem so bili ti trojčki že naloženi. Zagon iz posnetka je bistveno hitrejši, vendar še vedno traja približno eno uro, dokler Neptune ni na voljo za zahteve.

Pri začetnem nalaganju trojčkov v Neptune smo naleteli na različne napake.

{
 
 
 "errorCode" : "PARSING_ERROR",
 
 "errorMessage" : "Content after '.' is not allowed",
 
 "fileName" : [...],
 
 "recordNum" : 25
 
}

Nekatere od njih so bile napake pri razčlenjevanju, kot je prikazano zgoraj. Do danes še vedno nismo ugotovili, kaj točno je šlo na tej točki narobe. Tukaj bi zagotovo pomagalo malo več podrobnosti. Ta napaka se je pojavila pri približno 1 % vstavljenih trojk. Toda kar zadeva testiranje Neptuna, smo sprejeli dejstvo, da delamo le z 99 % informacij iz MusicBrainza.

Čeprav je to preprosto za ljudi, ki poznajo SPARQL, se zavedajte, da morajo biti trojčki RDF označeni z eksplicitnimi vrstami podatkov, kar lahko povzroči napake.

Pretočni prenos

Kot že omenjeno, Neptuna ne želimo uporabljati kot statično shrambo podatkov, temveč kot prožno in razvijajočo se bazo znanja. Zato smo morali najti načine za uvedbo novih trojčkov, ko se baza znanja spremeni, na primer, ko je objavljen nov album ali ko želimo materializirati izpeljano znanje.

Neptune podpira vnosne operaterje prek poizvedb SPARQL, tako neobdelanih kot na podlagi vzorcev. Spodaj bomo obravnavali oba pristopa.

Eden od naših ciljev je bil pretočni vnos podatkov. Razmislite o izdaji albuma v novi državi. Z vidika MusicBrainza to pomeni, da je za izdajo, ki vključuje albume, single, EP-je itd., v tabelo dodan nov vnos država izdaje. V RDF te informacije povežemo z dvema novima trojkama.

INSERT DATA { <http://musicbrainz.foo/release-country/737041> <http://musicbrainz.foo/release> <http://musicbrainz.foo/release/435759> };INSERT DATA { <http://musicbrainz.foo/release-country/737041> <http://musicbrainz.foo/date-year> "2018"^^<http://www.w3.org/2001/XMLSchema#int> };

Drugi cilj je bil pridobivanje novega znanja iz grafa. Recimo, da želimo pridobiti število izdaj, ki jih je vsak umetnik objavil v svoji karieri. Takšna poizvedba je precej zapletena in v Neptunu traja več kot 20 minut, zato moramo rezultat materializirati, da lahko to novo znanje ponovno uporabimo v kakšni drugi poizvedbi. Tako dodamo trojčke s temi informacijami nazaj v graf in vnesemo rezultat podpoizvedbe.

INSERT {
 
 
  ?artist_credit <http://musicbrainz.foo/number-of-releases> ?number_of_releases
 
} WHERE {
 
  SELECT ?artist_credit (COUNT(*) as ?number_of_releases)
 
  WHERE {
 
     ?artist_credit <http://musicbrainz.foo/rdftype> <http://musicbrainz.foo/artist-credit> .
 
     ?release_group <http://musicbrainz.foo/artist-credit> ?artist_credit .
 
     ?release_group <http://musicbrainz.foo/rdftype> <http://musicbrainz.foo/release-group> .
 
     ?release_group <http://musicbrainz.foo/name> ?release_group_name .
 
  }
 
  GROUP BY ?artist_credit
 
}

Dodajanje posameznih trojk v graf traja nekaj milisekund, medtem ko je čas izvajanja vstavljanja rezultata podpoizvedbe odvisen od časa izvajanja same podpoizvedbe.

Čeprav ga nismo pogosto uporabljali, vam Neptune omogoča tudi odstranitev trojčkov na podlagi vzorcev ali eksplicitnih podatkov, ki jih lahko uporabite za posodobitev informacij.

poizvedbe SPARQL

Z uvedbo prejšnjega podvzorca, ki vrne število izdaj za vsakega izvajalca, smo že uvedli prvo vrsto poizvedbe, na katero želimo odgovoriti z uporabo Neptuna. Izdelava poizvedbe v Neptunu je preprosta - pošljite zahtevo POST končni točki SPARQL, kot je prikazano spodaj:

curl -X POST --data-binary 'query=SELECT ?artist ?p ?o where {?artist <http://musicbrainz.foo/name> "Elton John" . ?artist ?p ?o . }' http://your-neptune-cluster:8182/sparql

Poleg tega smo uvedli poizvedbo, ki vrne profil izvajalca, ki vsebuje podatke o njegovem imenu, starosti ali državi izvora. Ne pozabite, da so izvajalci lahko posamezniki, skupine ali orkestri. Poleg tega te podatke dopolnjujemo s podatki o številu izdaj, ki so jih izvajalci izdali med letom. Za samostojne izvajalce vsako leto dodamo tudi informacije o skupinah, v katerih je izvajalec sodeloval.

SELECT
 
 
 ?artist_name ?year
 
 ?releases_in_year ?releases_up_year
 
 ?artist_type_name ?releases
 
 ?artist_gender ?artist_country_name
 
 ?artist_begin_date ?bands
 
 ?bands_in_year
 
WHERE {
 
 # Bands for each artist
 
 {
 
   SELECT
 
     ?year
 
     ?first_artist
 
     (group_concat(DISTINCT ?second_artist_name;separator=",") as ?bands)
 
     (COUNT(DISTINCT ?second_artist_name) AS ?bands_in_year)     
 
   WHERE {
 
     VALUES ?year {
 
       1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
 
       1970 1971 1972 1973 1974 1975 1976 1977 1978 1979
 
       1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
 
       1990 1991 1992 1993 1994 1995 1996 1997 1998 1999
 
       2000 2001 2002 2003 2004 2005 2006 2007 2008 2009
 
       2010 2011 2012 2013 2014 2015 2016 2017 2018
 
     }   
 
     ?first_artist <http://musicbrainz.foo/name> "Elton John" .
 
     ?first_artist <http://musicbrainz.foo/rdftype> <http://musicbrainz.foo/artist> .
 
     ?first_artist <http://musicbrainz.foo/type> ?first_artist_type .
 
     ?first_artist <http://musicbrainz.foo/name> ?first_artist_name .
 

 
 
     ?second_artist <http://musicbrainz.foo/rdftype> <http://musicbrainz.foo/artist> .
 
     ?second_artist <http://musicbrainz.foo/type> ?second_artist_type .
 
     ?second_artist <http://musicbrainz.foo/name> ?second_artist_name .
 
     optional { ?second_artist <http://musicbrainz.foo/begin-date-year> ?second_artist_begin_date_year . }
 
     optional { ?second_artist <http://musicbrainz.foo/end-date-year> ?second_artist_end_date_year . }
 

 
 
     ?l_artist_artist <http://musicbrainz.foo/entity0> ?first_artist .
 
     ?l_artist_artist <http://musicbrainz.foo/entity1> ?second_artist .
 
     ?l_artist_artist <http://musicbrainz.foo/link> ?link .
 

 
 
     optional { ?link <http://musicbrainz.foo/begin-date-year> ?link_begin_date_year . }
 
     optional { ?link <http://musicbrainz.foo/end-date-year> ?link_end_date_year . }
 

 
 
     FILTER (!bound(?link_begin_date_year) || ?link_begin_date_year <= ?year)
 
     FILTER (!bound(?link_end_date_year) || ?link_end_date_year >= ?year)
 
     FILTER (!bound(?second_artist_begin_date_year) || ?second_artist_begin_date_year <= ?year)
 
     FILTER (!bound(?second_artist_end_date_year) || ?second_artist_end_date_year >= ?year)
 
     FILTER (?first_artist_type NOT IN (<http://musicbrainz.foo/artist-type/2>, <http://musicbrainz.foo/artist-type/5>, <http://musicbrainz.foo/artist-type/6>))
 
     FILTER (?second_artist_type IN (<http://musicbrainz.foo/artist-type/2>, <http://musicbrainz.foo/artist-type/5>, <http://musicbrainz.foo/artist-type/6>))
 
   }
 
   GROUP BY ?first_artist ?year
 
 }
 
 # Releases up to a year
 
 {
 
   SELECT
 
     ?artist
 
     ?year
 
     (group_concat(DISTINCT ?release_name;separator=",") as ?releases)
 
     (COUNT(*) as ?releases_up_year)
 
   WHERE {
 
     VALUES ?year {
 
       1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
 
       1970 1971 1972 1973 1974 1975 1976 1977 1978 1979
 
       1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
 
       1990 1991 1992 1993 1994 1995 1996 1997 1998 1999
 
       2000 2001 2002 2003 2004 2005 2006 2007 2008 2009
 
       2010 2011 2012 2013 2014 2015 2016 2017 2018 
 
     }
 

 
 
     ?artist <http://musicbrainz.foo/name> "Elton John" .
 

 
 
     ?artist_credit_name <http://musicbrainz.foo/artist-credit> ?artist_credit .
 
     ?artist_credit_name <http://musicbrainz.foo/rdftype> <http://musicbrainz.foo/artist-credit-name> .
 
     ?artist_credit_name <http://musicbrainz.foo/artist> ?artist .
 
     ?artist_credit <http://musicbrainz.foo/rdftype> <http://musicbrainz.foo/artist-credit> .
 

 
 
     ?release_group <http://musicbrainz.foo/artist-credit> ?artist_credit .
 
     ?release_group <http://musicbrainz.foo/rdftype> <http://musicbrainz.foo/release-group> .
 
     ?release_group <http://musicbrainz.foo/name> ?release_group_name .
 
     ?release <http://musicbrainz.foo/release-group> ?release_group .
 
     ?release <http://musicbrainz.foo/name> ?release_name .
 
     ?release_country <http://musicbrainz.foo/release> ?release .
 
     ?release_country <http://musicbrainz.foo/date-year> ?release_country_year .
 

 
 
     FILTER (?release_country_year <= ?year)
 
   }
 
   GROUP BY ?artist ?year
 
 }
 
 # Releases in a year
 
 {
 
   SELECT ?artist ?year (COUNT(*) as ?releases_in_year)
 
   WHERE {
 
     VALUES ?year {
 
       1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
 
       1970 1971 1972 1973 1974 1975 1976 1977 1978 1979
 
       1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
 
       1990 1991 1992 1993 1994 1995 1996 1997 1998 1999
 
       2000 2001 2002 2003 2004 2005 2006 2007 2008 2009
 
       2010 2011 2012 2013 2014 2015 2016 2017 2018 
 
     }
 

 
 
     ?artist <http://musicbrainz.foo/name> "Elton John" .
 

 
 
     ?artist_credit_name <http://musicbrainz.foo/artist-credit> ?artist_credit .
 
     ?artist_credit_name <http://musicbrainz.foo/rdftype> <http://musicbrainz.foo/artist-credit-name> .
 
     ?artist_credit_name <http://musicbrainz.foo/artist> ?artist .
 
     ?artist_credit <http://musicbrainz.foo/rdftype> <http://musicbrainz.foo/artist-credit> .
 

 
 
     ?release_group <http://musicbrainz.foo/artist-credit> ?artist_credit .
 
     ?release_group <http://musicbrainz.foo/rdftype> <http://musicbrainz.foo/release-group> .
 
     ?release_group <http://musicbrainz.foo/name> ?release_group_name .
 
     ?release <http://musicbrainz.foo/release-group> ?release_group .
 
     ?release_country <http://musicbrainz.foo/release> ?release .
 
     ?release_country <http://musicbrainz.foo/date-year> ?release_country_year .
 

 
 
     FILTER (?release_country_year = ?year)
 
   }
 
   GROUP BY ?artist ?year
 
 }
 
 # Master data
 
 {
 
   SELECT DISTINCT ?artist ?artist_name ?artist_gender ?artist_begin_date ?artist_country_name
 
   WHERE {
 
     ?artist <http://musicbrainz.foo/name> ?artist_name .
 
     ?artist <http://musicbrainz.foo/name> "Elton John" .
 
     ?artist <http://musicbrainz.foo/gender> ?artist_gender_id .
 
     ?artist_gender_id <http://musicbrainz.foo/name> ?artist_gender .
 
     ?artist <http://musicbrainz.foo/area> ?birth_area .
 
     ?artist <http://musicbrainz.foo/begin-date-year> ?artist_begin_date.
 
     ?birth_area <http://musicbrainz.foo/name> ?artist_country_name .
 

 
 
     FILTER(datatype(?artist_begin_date) = xsd:int)
 
   }

Zaradi zapletenosti takšne poizvedbe smo lahko izvedli samo poizvedbe točk za določenega izvajalca, kot je Elton John, vendar ne za vse izvajalce. Zdi se, da Neptune ne optimizira takšne poizvedbe s spuščanjem filtrov v podizbore. Zato je treba vsak izbor ročno filtrirati po imenu izvajalca.

Neptune ima urne stroške in stroške na I/O. Za naše testiranje smo uporabili najmanjšo instanco Neptune, ki stane 0,384 USD/uro. V primeru zgornje poizvedbe, ki izračuna profil za enega samega delavca, nam Amazon zaračuna več deset tisoč V/I operacij, kar pomeni strošek 0.02 USD.

Izhod

Prvič, Amazon Neptune drži večino svojih obljub. Kot upravljana storitev je to baza podatkov grafov, ki jo je izjemno enostavno namestiti in jo je mogoče zagnati brez veliko konfiguracije. Tu je naših pet ključnih ugotovitev:

  • Množično nalaganje je preprosto, a počasno. Vendar se lahko zaplete s sporočili o napakah, ki niso zelo koristna.
  • Pretočni prenos podpira vse, kar smo pričakovali, in je bil precej hiter
  • Poizvedbe so preproste, vendar ne dovolj interaktivne za izvajanje analitičnih poizvedb
  • Poizvedbe SPARQL je treba optimizirati ročno
  • Plačila Amazon je težko oceniti, ker je težko oceniti količino podatkov, ki jih skenira poizvedba SPARQL.

To je vse. Prijavite se za brezplačni webinar na temo “Uravnavanje obremenitve”.


Vir: www.habr.com

Dodaj komentar