Амазон Нептунының алғашқы әсері

Сәлем, Хабаровск тұрғындары. Курстың басталуын күтумен «Әзірлеушілерге арналған AWS» Біз қызықты материалдың аудармасын дайындадық.

Амазон Нептунының алғашқы әсері

Көптеген жағдайларда бізге ұнайды bakdataКлиенттеріміздің веб-сайттарында көріп отырғанымыздай, сәйкес ақпарат нысандар арасындағы байланыстарда жасырылады, мысалы, пайдаланушылар арасындағы қарым-қатынастарды, элементтер арасындағы тәуелділіктерді немесе сенсорлар арасындағы байланыстарды талдау кезінде. Мұндай пайдалану жағдайлары әдетте графикте модельденеді. Осы жылдың басында Amazon өзінің жаңа графикалық деректер базасын Neptune шығарды. Бұл постта біз алғашқы идеяларымызбен, жақсы тәжірибелерімізбен және уақыт өте келе жақсартуға болатын нәрселермен бөліскіміз келеді.

Неліктен бізге Амазон Нептун қажет болды

Графикалық дерекқорлар жоғары байланысқан деректер жиынын олардың реляциялық баламаларына қарағанда жақсырақ өңдеуге уәде береді. Мұндай деректер жиындарында сәйкес ақпарат әдетте объектілер арасындағы қатынастарда сақталады. Біз Нептунды сынау үшін таңғажайып ашық деректер жобасын қолдандық MusicBrainz. MusicBrainz әртістер, әндер, альбом шығарылымдары немесе концерттер, сондай-ақ әннің артындағы орындаушы кіммен жұмыс істегені немесе альбом қай елде қашан шыққаны туралы ақпарат сияқты елестететін кез келген музыкалық метадеректерді жинайды. MusicBrainz-ті қандай да бір түрде музыка индустриясымен байланыстырылған нысандардың үлкен желісі ретінде қарастыруға болады.

MusicBrainz деректер жинағы реляциялық дерекқордың CSV демпі ретінде берілген. Жалпы, қоқыс 93 кестедегі шамамен 157 миллион жолды қамтиды. Осы кестелердің кейбіреулерінде әртістер, оқиғалар, жазбалар, шығарылымдар немесе тректер сияқты негізгі деректер болса, басқалары кестелерді байланыстыру — суретшілер мен жазбалар, басқа әртістер немесе шығарылымдар, т.б. арасындағы қарым-қатынастарды сақтау... Олар деректер жиынының графикалық құрылымын көрсетеді. Деректер жиынын RDF үштіктеріне түрлендіру кезінде біз шамамен 500 миллион дана алдық.

Біз жұмыс істейтін жоба серіктестерінің тәжірибесі мен әсерлеріне сүйене отырып, біз бұл білім базасы жаңа ақпаратты алу үшін пайдаланылатын жағдайды ұсынамыз. Бұған қоса, біз оның жүйелі түрде жаңартылуын күтеміз, мысалы, жаңа шығарылымдарды қосу немесе топ мүшелерін жаңарту.

реттеу

Күтілгендей, Amazon Neptune орнату оңай. Ол өте егжей-тегжейлі құжатталған. Сіз бірнеше рет басу арқылы графикалық дерекқорды іске қоса аласыз. Дегенмен, егжей-тегжейлі конфигурацияға келетін болсақ, қажетті ақпарат табу қиын. Сондықтан біз бір конфигурация параметрін көрсеткіміз келеді.

Амазон Нептунының алғашқы әсері
Параметр топтары үшін конфигурация скриншоты

Amazon компаниясы Нептун аз кідірістегі транзакциялық жұмыс жүктемелеріне назар аударатынын айтады, сондықтан әдепкі сұрау күту уақыты 120 секунд. Дегенмен, біз осы шекке үнемі жеткен көптеген аналитикалық пайдалану жағдайларын сынадық. Бұл күту уақытын Нептун үшін жаңа параметр тобын жасау және орнату арқылы өзгертуге болады neptune_query_timeout сәйкес шектеу.

Деректер жүктелуде

Төменде біз MusicBrainz деректерін Нептунға қалай жүктегенімізді егжей-тегжейлі талқылаймыз.

Үштік қатынастар

Алдымен біз MusicBrainz деректерін RDF үштіктеріне түрлендірдік. Сондықтан әрбір кесте үшін әрбір бағанның үштікте қалай көрсетілетінін анықтайтын үлгіні анықтадық. Бұл мысалда орындаушы кестесіндегі әрбір жол он екі 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> .

жаппай жүктеп салу

Нептунға үлкен көлемдегі деректерді жүктеудің ұсынылған жолы - S3 арқылы жаппай жүктеу процесі. Үштік файлдарды S3 жүйесіне жүктеп салғаннан кейін сіз POST сұрауы арқылы жүктеп салуды бастайсыз. Біздің жағдайда 24 миллион үшем үшін шамамен 500 сағат қажет болды. Біз тезірек болады деп күттік.

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

Нептунды іске қосқан сайын бұл ұзақ процесті болдырмау үшін біз осы үштіктер жүктелген суреттен дананы қалпына келтіруді шештік. Суреттен іске қосу айтарлықтай жылдамырақ, бірақ Нептун сұраныстар үшін қолжетімді болғанша бір сағаттай уақыт кетеді.

Бастапқыда Нептунға үштіктерді жүктеген кезде біз әртүрлі қателерге тап болдық.

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

Олардың кейбіреулері жоғарыда көрсетілгендей талдау қателері болды. Осы уақытқа дейін біз дәл осы сәтте ненің қате кеткенін әлі анықтаған жоқпыз. Кішкене егжей-тегжей бұл жерде міндетті түрде көмектеседі. Бұл қате енгізілген үштіктердің шамамен 1%-ында орын алды. Бірақ Нептунды сынауға келетін болсақ, біз MusicBrainz ақпаратының 99% ғана жұмыс істейтінімізді мойындадық.

Бұл SPARQL-пен таныс адамдар үшін оңай болса да, RDF үштіктері анық деректер түрлерімен түсіндірілуі керек екенін ескеріңіз, бұл қайтадан қателерді тудыруы мүмкін.

Ағынды жүктеп алу

Жоғарыда айтылғандай, біз Нептунды статикалық деректер қоймасы ретінде емес, икемді және дамып келе жатқан білім базасы ретінде пайдаланғымыз келмейді. Сондықтан бізге білім қоры өзгерген кезде, мысалы, жаңа альбом жарияланғанда немесе алынған білімді жүзеге асырғымыз келгенде, жаңа үштіктерді енгізу жолдарын табу керек болды.

Neptune шикі және үлгі негізіндегі SPARQL сұраулары арқылы енгізу операторларына қолдау көрсетеді. Төменде екі тәсілді де талқылаймыз.

Біздің мақсаттарымыздың бірі деректерді ағынды түрде енгізу болды. Жаңа елде альбом шығаруды қарастырыңыз. MusicBrainz көзқарасы бойынша бұл альбомдар, синглдар, EP және т.б. қамтитын шығарылым үшін кестеге жаңа жазба қосылатынын білдіреді. шығарылатын ел. RDF-те біз бұл ақпаратты екі жаңа үштікпен сәйкестендіреміз.

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

Тағы бір мақсат графиктен жаңа білім алу болды. Әр суретшінің өз мансабында шығарған шығарылымдарының санын алғымыз келеді делік. Мұндай сұрау өте күрделі және Нептунда 20 минуттан астам уақытты алады, сондықтан бұл жаңа білімді басқа сұрауда қайта пайдалану үшін нәтижені жүзеге асыруымыз керек. Сонымен, біз ішкі сұраудың нәтижесін енгізе отырып, осы ақпаратпен үш еселерді графикке қосамыз.

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
 
}

Графикке жалғыз үштік қосу бірнеше миллисекундты алады, ал ішкі сұрау нәтижесін кірістіру үшін орындалу уақыты ішкі сұраудың орындалу уақытына байланысты.

Біз оны жиі қолданбағанымызға қарамастан, Нептун сонымен қатар ақпаратты жаңарту үшін пайдаланылуы мүмкін үлгілер немесе анық деректер негізінде үштіктерді жоюға мүмкіндік береді.

SPARQL сұраулары

Әрбір орындаушы үшін шығарылымдар санын қайтаратын алдыңғы ішкі үлгіні енгізу арқылы біз Нептун көмегімен жауап бергіміз келетін сұраудың бірінші түрін енгіздік. Нептунда сұрау салу оңай - төменде көрсетілгендей SPARQL соңғы нүктесіне POST сұрауын жіберіңіз:

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

Бұған қоса, біз олардың аты, жасы немесе шыққан елі туралы ақпаратты қамтитын орындаушы профилін қайтаратын сұрауды орындадық. Орындаушылар жеке адамдар, топтар немесе оркестрлер болуы мүмкін екенін есте сақтаңыз. Сонымен қатар, біз бұл деректерді суретшілердің жыл ішінде шығарған шығарылымдары туралы ақпаратпен толықтырамыз. Жеке әртістер үшін біз әр жыл сайын қатысқан топтар туралы ақпаратты қосамыз.

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

Мұндай сұраудың күрделілігіне байланысты біз Элтон Джон сияқты белгілі бір суретші үшін ғана нүктелік сұрауларды орындай алдық, бірақ барлық суретшілер үшін емес. Нептун мұндай сұрауды ішкі таңдауларға сүзгілерді тастау арқылы оңтайландырмайтын сияқты. Сондықтан әрбір таңдауды орындаушы аты бойынша қолмен сүзгілеу керек.

Нептунның сағаттық және әр I/O зарядтары бар. Тестілеу үшін біз сағатына $0,384 тұратын ең аз Neptune данасын қолдандық. Бір жұмысшы үшін профильді есептейтін жоғарыдағы сұрау жағдайында Amazon бізден ондаған мың енгізу/шығару операциялары үшін ақы алады, бұл $0.02 құнын білдіреді.

қорытынды

Біріншіден, Amazon Neptune өз уәделерінің көпшілігін орындайды. Басқарылатын қызмет ретінде бұл орнату өте оңай және көп конфигурациясыз жұмыс істей алатын графикалық дерекқор. Міне, біздің бес негізгі тұжырымымыз:

  • Жаппай жүктеп салу оңай, бірақ баяу. Бірақ бұл өте пайдалы емес қате туралы хабарлармен қиындауы мүмкін.
  • Ағынды жүктеп алу біз күткеннің бәрін қолдайды және өте жылдам болды
  • Сұраулар қарапайым, бірақ аналитикалық сұрауларды орындау үшін жеткілікті интерактивті емес
  • SPARQL сұраулары қолмен оңтайландырылған болуы керек
  • Amazon төлемдерін бағалау қиын, себебі SPARQL сұрауы арқылы сканерленген деректер көлемін бағалау қиын.

Бар болғаны. Жазылу «Жүктемені теңестіру» тақырыбындағы тегін вебинар.


Ақпарат көзі: www.habr.com

пікір қалдыру