Amazon Neptune Erste Eindrücke

Gruß, Chabrowsk. Im Vorfeld des Starts des AWS for Developers- Kurses haben wir eine Übersetzung von interessantem Material vorbereitet.




In vielen Benutzerfällen, die wir als Bakdata auf den Websites unserer Kunden sehen, werden relevante Informationen in Beziehungen zwischen Entitäten verborgen, z. B. bei der Analyse von Beziehungen zwischen Benutzern, Abhängigkeiten zwischen Elementen oder Verbindungen zwischen Sensoren. Solche Benutzerfälle werden normalerweise in einem Diagramm modelliert. Anfang dieses Jahres veröffentlichte Amazon die neue Neptune-Grafikdatenbank. In diesem Beitrag möchten wir Ihnen unsere ersten Ideen, bewährten Verfahren und Möglichkeiten mitteilen, die im Laufe der Zeit verbessert werden können.

Warum brauchen wir Amazon Neptune?


Grafikdatenbanken versprechen, stark verbundene Datensätze besser zu verarbeiten als ihre relationalen Entsprechungen. In solchen Datensätzen werden relevante Informationen normalerweise in Beziehungen zwischen Objekten gespeichert. Zum Testen von Neptune haben wir ein erstaunliches Projekt mit Open Data MusicBrainz verwendet . MusicBrainz sammelt alle denkbaren Metadaten über Musik, zum Beispiel Informationen über Künstler, Songs, Albumveröffentlichungen oder Konzerte sowie darüber, mit wem der Künstler, der den Song erstellt hat, zusammengearbeitet hat oder wann das Album in welchem ​​Land veröffentlicht wurde. MusicBrainz kann als ein riesiges Netzwerk von Unternehmen angesehen werden, die in irgendeiner Weise mit der Musikindustrie verbunden sind.

Das MusicBrainz-Dataset wird als Speicherauszug der relationalen CSV-Datenbank bereitgestellt. Insgesamt enthält der Speicherauszug ungefähr 93 Millionen Zeilen in 157 Tabellen. Während einige dieser Tabellen Stammdaten enthalten, wie z. B. Künstler, Ereignisse, Aufzeichnungen, Veröffentlichungen oder Tracks, speichern andere - Verknüpfungstabellen - Beziehungen zwischen Künstlern und Aufzeichnungen, anderen Künstlern oder Veröffentlichungen usw. Sie demonstrieren die grafische Struktur des Sets Daten. Bei der Konvertierung des Datensatzes in RDF-Tripel erhielten wir ungefähr 500 Millionen Kopien.

Basierend auf den Erfahrungen und Eindrücken der Projektpartner, mit denen wir zusammenarbeiten, präsentieren wir eine Umgebung, in der diese Wissensbasis verwendet wird, um neue Informationen zu erhalten. Darüber hinaus gehen wir davon aus, dass es regelmäßig aktualisiert wird, beispielsweise durch Hinzufügen neuer Versionen oder Aktualisieren von Gruppenmitgliedern.

Anpassung


Wie erwartet ist die Installation von Amazon Neptune einfach. Es ist detailliert dokumentiert . Sie können die Diagrammdatenbank mit nur wenigen Klicks starten. Wenn es jedoch um eine detailliertere Konfiguration geht, sind die benötigten Informationen schwer zu finden. Daher möchten wir auf einen Konfigurationsparameter verweisen.


Der Konfigurations-Screenshot für die

Amazon- Parametergruppen besagt, dass Neptune sich auf Transaktions-Workloads mit geringer Latenz konzentriert, sodass das Standardzeitlimit 120 Sekunden beträgt. Wir haben jedoch viele analytische Anwenderfälle getestet, in denen wir diese Grenze regelmäßig erreicht haben. Sie können dieses Zeitlimit ändern, indem Sie eine neue Parametergruppe für Neptun erstellen und auf einstellenneptune_query_timeout entsprechende Einschränkung.

Laden von Daten


Im Folgenden werden wir detailliert diskutieren, wie wir MusicBrainz-Daten auf Neptune hochgeladen haben.

Beziehungen zu dritt


Zuerst haben wir die MusicBrainz-Daten in RDF-Tripel konvertiert. Daher haben wir für jede Tabelle eine Vorlage definiert, die bestimmt, wie jede Spalte in den oberen drei dargestellt wird. In diesem Beispiel wird jede Zeile aus der Executor-Tabelle zwölf RDF-Tripeln zugeordnet.

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


Massen-Upload


Das vorgeschlagene Verfahren zum Laden großer Datenmengen in Neptun ist das Massenladen über S3. Nachdem Sie Ihre Triple-Dateien in S3 hochgeladen haben, starten Sie den Download mithilfe einer POST-Anforderung. In unserem Fall dauerte es ungefähr 24 Stunden für 500 Millionen Tripel. Wir haben erwartet, dass es schneller geht.

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

Um diesen langwierigen Prozess bei jedem Start von Neptune zu vermeiden, haben wir beschlossen, die Instanz aus dem Snapshot wiederherzustellen, in den diese Tripel bereits geladen sind. Das Starten eines Schnappschusses ist viel schneller, aber es dauert immer noch ungefähr eine Stunde, bis Neptune für Anfragen verfügbar ist.

Beim ersten Laden von Triple in Neptune sind verschiedene Fehler aufgetreten.

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

Einige von ihnen waren Analysefehler, wie oben gezeigt. Bis heute haben wir noch nicht herausgefunden, was genau in diesem Moment schief gelaufen ist. Ein bisschen mehr Detail würde hier definitiv helfen. Dieser Fehler trat bei etwa 1% der eingefügten Tripel auf. Beim Testen von Neptune haben wir jedoch akzeptiert, dass wir nur mit 99% der Informationen von MusicBrainz arbeiten.

Beachten Sie, dass RDF-Tripel mit expliziten Datentypen versehen werden müssen, auch wenn dies für SPARQL-Benutzer einfach ist. Dies kann wiederum zu Fehlern führen.

Streaming-Download


Wie oben erwähnt, möchten wir Neptune nicht als statisches Data Warehouse verwenden, sondern als flexible und sich weiterentwickelnde Wissensbasis. Daher mussten wir Wege finden, um neue Tripel einzuführen, wenn wir die Wissensbasis ändern, zum Beispiel wenn ein neues Album veröffentlicht wird oder wenn wir abgeleitetes Wissen materialisieren wollen.

Neptune unterstützt Eingabeoperatoren über SPARQL-Abfragen, sowohl mit Rohdaten als auch basierend auf Beispielen. Wir werden beide Ansätze unten diskutieren.

Eines unserer Ziele war die Eingabe von Daten im Streaming-Modus. Betrachten Sie die Veröffentlichung eines Albums in einem neuen Land. Aus Sicht von MusicBrainz bedeutet dies, dass für eine Veröffentlichung, die Alben, Singles, EPs usw. enthält, ein neuer Datensatz zur Release-Country- Tabelle hinzugefügt wird. In RDF vergleichen wir diese Informationen mit zwei neuen Tripeln.

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

Ein weiteres Ziel war es, neues Wissen aus der Grafik zu gewinnen. Angenommen, wir möchten die Anzahl der Veröffentlichungen ermitteln, die jeder Künstler in seiner Karriere veröffentlicht hat. Eine solche Abfrage ist ziemlich kompliziert und dauert in Neptun mehr als 20 Minuten. Daher müssen wir das Ergebnis materialisieren, um dieses neue Wissen in einer anderen Abfrage wiederzuverwenden. Aus diesem Grund fügen wir dem Diagramm Tripel mit diesen Informationen hinzu und führen das Ergebnis der Unterabfrage ein.

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
 
}

Das Hinzufügen einzelner Tripel zu einem Diagramm dauert mehrere Millisekunden, während die Ausführungszeit zum Einfügen des Ergebnisses einer Unterabfrage von der Ausführungszeit der Unterabfrage selbst abhängt.

Trotz der Tatsache, dass wir es nicht oft verwendet haben, können Sie mit Neptune auch Tripel löschen, die auf Beispielen oder expliziten Daten basieren, die zum Aktualisieren von Informationen verwendet werden können.

SPARQL-Abfragen


Mit dem vorherigen Teilbeispiel, das die Anzahl der Veröffentlichungen für jeden Künstler zurückgibt, haben wir bereits die erste Art von Anfrage eingeführt, die wir mit Neptune beantworten möchten. Das Erstellen einer Abfrage in Neptune ist einfach: Senden Sie eine POST-Anforderung an den SPARQL-Endpunkt, wie unten gezeigt:

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

Darüber hinaus haben wir eine Abfrage implementiert, die ein Künstlerprofil zurückgibt, das Informationen zu Name, Alter oder Herkunftsland enthält. Denken Sie daran, dass es sich bei den Darstellern um Personen, Gruppen oder Orchester handeln kann. Zusätzlich ergänzen wir diese Daten mit Informationen über die Anzahl der Veröffentlichungen, die Künstler im Laufe des Jahres veröffentlicht haben. Für Solokünstler fügen wir auch Informationen zu den Gruppen hinzu, an denen diese Künstler jedes Jahr teilgenommen haben.

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

Aufgrund der Komplexität einer solchen Anfrage konnten wir nur Punktabfragen für einen bestimmten Künstler wie Elton John durchführen, jedoch nicht für alle Künstler. Neptune scheint eine solche Abfrage nicht zu optimieren, indem Filter in Teilproben weggelassen werden. Daher muss jedes Sample manuell nach dem Namen des Künstlers gefiltert werden.

Neptune hat sowohl stündlich als auch für jede E / A-Operation bezahlt. Für unsere Tests haben wir die kleinste Neptune-Instanz verwendet, die 0,384 USD / Stunde kostet. Im Fall der obigen Anfrage, die das Profil für einen Künstler berechnet, berechnet Amazon uns Zehntausende von E / A, was Kosten in Höhe von 0,02 USD bedeutet.

Fazit


Zunächst einmal hält Amazon Neptune die meisten seiner Versprechen. Als verwalteter Dienst handelt es sich um eine Grafikdatenbank, die extrem einfach zu installieren ist und ohne viele Einstellungen gestartet werden kann. Hier sind unsere fünf wichtigsten Ergebnisse:

  • Der Massen-Upload ist einfach, aber langsam. Es kann jedoch aufgrund von Fehlermeldungen kompliziert werden, die nicht viel helfen
  • Das Laden von Streams unterstützte alles, was wir erwartet hatten, und war schnell genug
  • Abfragen sind einfach, aber nicht interaktiv genug, um analytische Abfragen durchzuführen
  • SPARQL-Abfragen müssen manuell optimiert werden
  • Amazon-Zahlungen sind schwer zu bewerten, da es schwierig ist, die von einer SPARQL-Abfrage gescannte Datenmenge abzuschätzen.

Das ist alles. Melden Sie sich für ein kostenloses Webinar zum Thema „Load Balancing“ an .

All Articles