Primeres impressions d'Amazon Neptune

Salutacions, habitants de Khabrovsk. En previsió de l'inici del curs "AWS per a desenvolupadors" Hem preparat una traducció de material interessant.

Primeres impressions d'Amazon Neptune

En molts casos d'ús que ens agraden bakdataCom veiem als llocs web dels nostres clients, la informació rellevant s'amaga a les connexions entre entitats, per exemple quan s'analitza les relacions entre usuaris, dependències entre elements o connexions entre sensors. Aquests casos d'ús solen ser modelats en un gràfic. A principis d'aquest any, Amazon va llançar la seva nova base de dades de gràfics, Neptune. En aquest post volem compartir les nostres primeres idees, bones pràctiques i què es pot millorar amb el temps.

Per què necessitàvem Amazon Neptune

Les bases de dades de gràfics prometen gestionar conjunts de dades altament connectats millor que els seus equivalents relacionals. En aquests conjunts de dades, la informació rellevant normalment s'emmagatzema en relacions entre objectes. Hem utilitzat un increïble projecte de dades obertes per provar Neptú MusicBrainz. MusicBrainz recull tot tipus de metadades musicals imaginables, com ara informació sobre artistes, cançons, llançaments d'àlbums o concerts, així com amb qui va col·laborar l'artista darrere de la cançó o quan es va publicar l'àlbum en quin país. MusicBrainz es pot veure com una xarxa enorme d'entitats connectades d'alguna manera a la indústria musical.

El conjunt de dades MusicBrainz es proporciona com a bolcat CSV d'una base de dades relacional. En total, l'abocador conté uns 93 milions de files en 157 taules. Tot i que algunes d'aquestes taules contenen dades bàsiques com ara artistes, esdeveniments, enregistraments, llançaments o cançons, d'altres taules d'enllaç — emmagatzemar relacions entre artistes i enregistraments, altres artistes o llançaments, etc... Demostren l'estructura gràfica d'un conjunt de dades. En convertir el conjunt de dades en triples RDF, vam obtenir aproximadament 500 milions d'instàncies.

A partir de l'experiència i les impressions dels socis del projecte amb qui treballem, presentem un entorn en el qual aquesta base de coneixement s'utilitza per obtenir nova informació. A més, esperem que s'actualitzi periòdicament, per exemple, afegint noves versions o actualitzant els membres del grup.

ajust

Com era d'esperar, instal·lar Amazon Neptune és senzill. Ella és força detallada documentat. Podeu llançar una base de dades de gràfics amb només uns quants clics. Tanmateix, quan es tracta d'una configuració més detallada, informació necessària difícil de trobar. Per tant, volem apuntar a un paràmetre de configuració.

Primeres impressions d'Amazon Neptune
Captura de pantalla de configuració per a grups de paràmetres

Amazon diu que Neptune se centra en càrregues de treball transaccionals de baixa latència, motiu pel qual el temps d'espera de sol·licitud predeterminat és de 120 segons. Tanmateix, hem provat molts casos d'ús analític en els quals arribem regularment a aquest límit. Aquest temps d'espera es pot canviar mitjançant la creació d'un nou grup de paràmetres per a Neptú i la configuració neptune_query_timeout restricció corresponent.

Carregant dades

A continuació parlarem amb detall de com hem carregat les dades de MusicBrainz a Neptune.

Relacions de tres

Primer, vam convertir les dades de MusicBrainz en triples RDF. Per tant, per a cada taula, hem definit una plantilla que defineix com es representa cada columna en el triple. En aquest exemple, cada fila de la taula d'intèrprets s'assigna a dotze triples 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> .

càrrega massiva

La manera suggerida de carregar grans quantitats de dades a Neptune és mitjançant el procés de càrrega massiva mitjançant S3. Després de carregar els fitxers de triples a S3, comenceu la càrrega mitjançant una sol·licitud POST. En el nostre cas, van trigar unes 24 hores a 500 milions de trillissos. Esperàvem que fos més ràpid.

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

Per evitar aquest llarg procés cada vegada que iniciem Neptune, vam decidir restaurar la instància a partir d'una instantània en què ja estaven carregats aquests triplets. L'execució des d'una instantània és significativament més ràpida, però encara triga aproximadament una hora fins que Neptune estigui disponible per a les sol·licituds.

Quan vam carregar inicialment triplets a Neptú, vam trobar diversos errors.

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

Alguns d'ells eren errors d'anàlisi, com es mostra més amunt. Fins ara, encara no hem esbrinat què ha fallat exactament en aquest moment. Sens dubte, una mica més de detall ajudaria aquí. Aquest error s'ha produït durant aproximadament l'1% dels triples inserits. Però pel que fa a la prova de Neptune, vam acceptar el fet que només treballem amb el 99% de la informació de MusicBrainz.

Tot i que això és fàcil per a persones familiaritzades amb SPARQL, tingueu en compte que els triples RDF s'han d'anotar amb tipus de dades explícits, que de nou poden provocar errors.

Descàrrega en streaming

Com s'ha esmentat anteriorment, no volem utilitzar Neptune com a magatzem de dades estàtiques, sinó com una base de coneixement flexible i en evolució. Per tant, calia trobar maneres d'introduir nous triples quan canvia la base de coneixement, per exemple quan es publica un nou àlbum o quan volem materialitzar coneixements derivats.

Neptune admet operadors d'entrada mitjançant consultes SPARQL, tant en brut com en mostres. A continuació parlarem dels dos enfocaments.

Un dels nostres objectius era introduir dades en streaming. Penseu en publicar un àlbum en un país nou. Des de la perspectiva de MusicBrainz, això significa que per a un llançament que inclou àlbums, senzills, EP, etc., s'afegeix una nova entrada a la taula. país d'alliberament. A RDF, combinem aquesta informació amb dos nous triples.

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

Un altre objectiu era obtenir nous coneixements a partir del gràfic. Suposem que volem obtenir el nombre de llançaments que ha publicat cada artista al llarg de la seva carrera. Aquesta consulta és força complexa i triga més de 20 minuts a Neptú, per la qual cosa hem de materialitzar el resultat per tal de reutilitzar aquest nou coneixement en alguna altra consulta. Així que afegim triples amb aquesta informació de nou al gràfic, introduint el resultat de la subconsulta.

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
 
}

L'addició de triples senzills al gràfic triga uns quants mil·lisegons, mentre que el temps d'execució per inserir el resultat d'una subconsulta depèn del temps d'execució de la subconsulta.

Tot i que no el vam fer servir sovint, Neptune també us permet eliminar els triplets basats en mostres o dades explícites, que es poden utilitzar per actualitzar la informació.

Consultes SPARQL

En introduir la submostra anterior, que retorna el nombre de llançaments per a cada artista, ja hem introduït el primer tipus de consulta que volem respondre amb Neptune. Crear una consulta a Neptune és fàcil: envieu una sol·licitud POST al punt final SPARQL, tal com es mostra a continuació:

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

A més, hem implementat una consulta que retorna un perfil d'artista que conté informació sobre el seu nom, edat o país d'origen. Tingueu en compte que els intèrprets poden ser individus, bandes o orquestres. A més, complementem aquestes dades amb informació sobre el nombre de llançaments publicats pels artistes durant l'any. Per als artistes solistes, també afegim informació sobre les bandes en què va participar cada any l'artista.

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

A causa de la complexitat d'aquesta consulta, només podíem fer consultes de punts per a un artista concret, com ara Elton John, però no per a tots els artistes. Neptú no sembla optimitzar aquesta consulta deixant caure els filtres en subseleccions. Per tant, cada selecció s'ha de filtrar manualment pel nom de l'artista.

Neptune té càrrecs per hora i per E/S. Per a les nostres proves, hem utilitzat la instància mínima de Neptú, que costa 0,384 dòlars per hora. En el cas de la consulta anterior, que calcula el perfil d'un sol treballador, Amazon ens cobra desenes de milers d'operacions d'E/S, la qual cosa implica un cost de 0.02 dòlars.

Sortida

En primer lloc, Amazon Neptune compleix la majoria de les seves promeses. Com a servei gestionat, és una base de dades de gràfics extremadament fàcil d'instal·lar i que pot estar en funcionament sense molta configuració. Aquestes són les nostres cinc conclusions clau:

  • La càrrega massiva és fàcil però lenta. Però es pot complicar amb missatges d'error que no són gaire útils.
  • La descàrrega en streaming admet tot el que esperàvem i va ser bastant ràpid
  • Les consultes són senzilles, però no prou interactives per executar consultes analítiques
  • Les consultes SPARQL s'han d'optimitzar manualment
  • Els pagaments d'Amazon són difícils d'estimar perquè és difícil estimar la quantitat de dades escanejades per una consulta SPARQL.

Això és tot. Inscriu-te seminari web gratuït sobre el tema "Equilibri de càrrega".


Font: www.habr.com

Afegeix comentari