Prvi utisci o Amazon Neptunu

Pozdrav, stanovnici Khabrovsk. U iščekivanju početka kursa "AWS za programere" Pripremili smo prijevod zanimljivog materijala.

Prvi utisci o Amazon Neptunu

U mnogim slučajevima upotrebe koji nam se sviđaju bakdataKao što vidimo na web stranicama naših klijenata, relevantne informacije su skrivene u vezama između entiteta, na primjer kada se analiziraju odnosi između korisnika, zavisnosti između elemenata ili veze između senzora. Takvi slučajevi upotrebe obično se modeliraju na grafu. Ranije ove godine, Amazon je objavio svoju novu bazu podataka grafova, Neptun. U ovom postu želimo podijeliti naše prve ideje, dobre prakse i ono što se vremenom može poboljšati.

Zašto nam je trebao Amazon Neptun

Grafičke baze podataka obećavaju da će bolje rukovati visoko povezanim skupovima podataka od njihovih relacijskih ekvivalenata. U takvim skupovima podataka, relevantne informacije se obično pohranjuju u odnosima između objekata. Koristili smo neverovatan projekat otvorenih podataka da testiramo Neptun MusicBrainz. MusicBrainz prikuplja sve vrste muzičkih metapodataka koje se može zamisliti, kao što su informacije o izvođačima, pjesmama, izdanjima albuma ili koncertima, kao i o tome s kim je umjetnik koji stoji iza pjesme sarađivao ili kada je album objavljen u kojoj zemlji. MusicBrainz se može posmatrati kao ogromna mreža entiteta koji su na neki način povezani sa muzičkom industrijom.

MusicBrainz skup podataka je obezbeđen kao CSV dump relacione baze podataka. Ukupno, dump sadrži oko 93 miliona redova u 157 tabela. Dok neke od ovih tabela sadrže osnovne podatke kao što su izvođači, događaji, snimke, izdanja ili numere, druge link tabele — pohranjuju odnose između izvođača i snimaka, drugih umjetnika ili izdanja, itd... Oni demonstriraju strukturu grafikona skupa podataka. Kada smo konvertovali skup podataka u RDF trojke, dobili smo približno 500 miliona instanci.

Na osnovu iskustva i utisaka partnera na projektu sa kojima radimo, predstavljamo okruženje u kojem se ova baza znanja koristi za dobijanje novih informacija. Osim toga, očekujemo da se redovno ažurira, na primjer dodavanjem novih izdanja ili ažuriranjem članova grupe.

podešavanje

Kao što se i očekivalo, instalacija Amazon Neptuna je jednostavna. Ona je prilično detaljna dokumentovano. Možete pokrenuti bazu podataka grafova u samo nekoliko klikova. Međutim, kada je u pitanju detaljnija konfiguracija, potrebne informacije teško naći. Stoga želimo ukazati na jedan konfiguracijski parametar.

Prvi utisci o Amazon Neptunu
Snimak ekrana konfiguracije za grupe parametara

Amazon kaže da se Neptune fokusira na transakcijska opterećenja s malim kašnjenjem, zbog čega je standardno vrijeme čekanja zahtjeva 120 sekundi. Međutim, testirali smo mnoge analitičke slučajeve upotrebe u kojima smo redovno dostizali ovu granicu. Ovo vremensko ograničenje se može promijeniti kreiranjem nove grupe parametara za Neptun i postavljanjem neptune_query_timeout odgovarajuće ograničenje.

Učitavanje podataka

U nastavku ćemo detaljno raspravljati o tome kako smo učitali MusicBrainz podatke u Neptun.

Veze u troje

Prvo smo konvertovali MusicBrainz podatke u RDF trojke. Stoga smo za svaku tablicu definirali šablon koji definira kako je svaka kolona predstavljena u trojci. U ovom primjeru, svaki red iz tablice izvođača je mapiran na dvanaest RDF trojki.

<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> .

masovno otpremanje

Predloženi način za učitavanje velike količine podataka u Neptune je proces masovnog učitavanja putem S3. Nakon učitavanja vaših trostrukih fajlova na S3, započinjete otpremanje pomoću POST zahtjeva. U našem slučaju, trebalo je oko 24 sata za 500 miliona trojki. Očekivali smo da će biti brže.

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"
 
}'

Kako bismo izbjegli ovaj dugotrajan proces svaki put kada pokrenemo Neptune, odlučili smo da vratimo instancu sa snimka u kojem su ove trojke već učitane. Pokretanje sa snimka je znatno brže, ali i dalje traje oko sat vremena dok Neptun ne bude dostupan za zahtjeve.

Prilikom početnog učitavanja trojki u Neptun, naišli smo na razne greške.

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

Neke od njih su bile greške raščlanjivanja, kao što je prikazano gore. Do danas još uvijek nismo shvatili šta je tačno pošlo po zlu u ovom trenutku. Malo više detalja bi tu svakako pomoglo. Ova greška se dogodila za otprilike 1% umetnutih trojki. Ali što se tiče testiranja Neptuna, prihvatili smo činjenicu da radimo samo sa 99% informacija iz MusicBrainza.

Iako je ovo lako za ljude koji su upoznati sa SPARQL-om, imajte na umu da RDF trojke moraju biti označene eksplicitnim tipovima podataka, što opet može uzrokovati greške.

Preuzimanje prijenosa

Kao što je gore pomenuto, ne želimo da koristimo Neptun kao statično skladište podataka, već kao fleksibilnu bazu znanja koja se razvija. Stoga smo morali pronaći načine da uvedemo nove trojke kada se baza znanja promijeni, na primjer kada se objavi novi album ili kada želimo materijalizirati izvedeno znanje.

Neptune podržava operatore unosa kroz SPARQL upite, sirove i bazirane na uzorku. U nastavku ćemo raspravljati o oba pristupa.

Jedan od naših ciljeva je bio unos podataka na streaming način. Razmislite o izdavanju albuma u novoj zemlji. Iz perspektive MusicBrainza, to znači da se za izdanje koje uključuje albume, singlove, EP-ove, itd., dodaje novi unos u tabelu slobodna zemlja. U RDF-u ovu informaciju povezujemo s dvije nove trojke.

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 bio sticanje novih znanja iz grafa. Recimo da želimo da dobijemo broj izdanja koje je svaki umetnik objavio u svojoj karijeri. Takav upit je prilično složen i traje više od 20 minuta u Neptunu, tako da moramo materijalizirati rezultat kako bismo ponovo iskoristili ovo novo znanje u nekom drugom upitu. Tako da dodajemo trojke sa ovom informacijom nazad u graf, unoseći rezultat podupita.

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
 
}

Dodavanje pojedinačnih trojki u graf traje nekoliko milisekundi, dok vrijeme izvršenja za umetanje rezultata potupita ovisi o vremenu izvršenja samog podupita.

Iako ga nismo često koristili, Neptun vam također omogućava uklanjanje trojki na osnovu uzoraka ili eksplicitnih podataka, koji se mogu koristiti za ažuriranje informacija.

SPARQL upiti

Uvođenjem prethodnog poduzorka, koji vraća broj izdanja za svakog izvođača, već smo uveli prvi tip upita na koji želimo odgovoriti pomoću Neptuna. Izrada upita u Neptuneu je jednostavna - pošaljite POST zahtjev na SPARQL krajnju tačku, kao što je prikazano u nastavku:

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

Osim toga, implementirali smo upit koji vraća profil umjetnika koji sadrži informacije o njihovom imenu, dobi ili zemlji porijekla. Imajte na umu da izvođači mogu biti pojedinci, bendovi ili orkestri. Osim toga, ove podatke dopunjavamo informacijama o broju izdanja koje su umjetnici objavili tokom godine. Za solo izvođače dodajemo i informacije o bendovima u kojima je umjetnik učestvovao svake godine.

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)
 
   }

Zbog složenosti takvog upita, mogli smo izvoditi upite po točkama samo za određenog umjetnika, kao što je Elton John, ali ne i za sve umjetnike. Čini se da Neptun ne optimizuje takav upit ispuštanjem filtera u podselekte. Stoga, svaki odabir mora biti ručno filtriran prema imenu izvođača.

Neptun ima i satnu i per-I/O naplatu. Za naše testiranje koristili smo minimalnu instancu Neptuna, koja košta 0,384 USD po satu. U slučaju gornjeg upita, koji izračunava profil za jednog radnika, Amazon nam naplaćuje desetine hiljada I/O operacija, što implicira trošak od 0.02 USD.

zaključak

Prvo, Amazon Neptune drži većinu svojih obećanja. Kao upravljana usluga, to je baza podataka grafova koju je izuzetno lako instalirati i koja se može pokrenuti i pokrenuti bez mnogo konfiguracije. Evo naših pet ključnih nalaza:

  • Skupno otpremanje je jednostavno, ali sporo. Ali može se zakomplikovati s porukama o greškama koje nisu od velike pomoći.
  • Streaming preuzimanje podržava sve što smo očekivali i bilo je prilično brzo
  • Upiti su jednostavni, ali nisu dovoljno interaktivni za pokretanje analitičkih upita
  • SPARQL upiti moraju biti optimizirani ručno
  • Amazon plaćanja je teško procijeniti jer je teško procijeniti količinu podataka skeniranih SPARQL upitom.

To je sve. Prijavi se za besplatni webinar na temu "Uravnotežavanje opterećenja".


izvor: www.habr.com

Dodajte komentar