الأمازون نبتون الانطباعات الأولى

تحية ، خابروفسك. تحسبًا لبدء دورة AWS للمطورين ، قمنا بإعداد ترجمة لمواد مثيرة للاهتمام.




في العديد من حالات المستخدمين التي نراها ، كمعلومات bakdata ، على مواقع عملائنا ، يتم إخفاء المعلومات ذات الصلة في العلاقات بين الكيانات ، على سبيل المثال ، عند تحليل العلاقات بين المستخدمين أو التبعيات بين العناصر أو الاتصالات بين أجهزة الاستشعار. عادة ما يتم تصميم حالات المستخدم هذه على رسم بياني. في وقت سابق من هذا العام ، أصدرت أمازون قاعدة بيانات نبتون الجديدة للرسم البياني. في هذا المنشور ، نريد مشاركة أفكارنا الأولى والممارسات الجيدة وما يمكن تحسينه بمرور الوقت.

لماذا نحتاج إلى أمازون نبتون


تعد قواعد بيانات الرسم البياني بمعالجة مجموعات البيانات عالية الارتباط بشكل أفضل من معادلاتها العلائقية. في مجموعات البيانات هذه ، عادةً ما يتم تخزين المعلومات ذات الصلة في العلاقات بين الكائنات. لاختبار نبتون استخدمنا مشروعًا رائعًا ببيانات مفتوحة MusicBrainz . يجمع MusicBrainz أي بيانات وصفية يمكن تصورها عن الموسيقى ، مثل معلومات عن الفنانين أو الأغاني أو إصدارات الألبوم أو الحفلات الموسيقية ، بالإضافة إلى الفنان الذي أنشأ الأغنية التي تعاونت معها أو عندما تم إصدار الألبوم في أي بلد. يمكن اعتبار MusicBrainz شبكة ضخمة من الكيانات التي ترتبط بطريقة ما بصناعة الموسيقى.

يتم توفير مجموعة بيانات MusicBrainz كمستودع لقاعدة بيانات CSV العلائقية. في المجموع ، يحتوي التفريغ على حوالي 93 مليون صف في 157 جدولًا. بينما تحتوي بعض هذه الجداول على بيانات رئيسية ، مثل الفنانين ، والأحداث ، والسجلات ، والإصدارات أو المسارات ، والبعض الآخر - ربط الجداول - تخزين العلاقات بين الفنانين والسجلات ، وغيرهم من الفنانين أو الإصدارات ، وما إلى ذلك ... فهي توضح البنية الرسومية للمجموعة البيانات. عند تحويل مجموعة البيانات إلى ثلاث مرات RDF ، حصلنا على حوالي 500 مليون نسخة.

استنادًا إلى خبرة وانطباعات شركاء المشروع الذين نعمل معهم ، نقدم إطارًا يتم فيه استخدام قاعدة المعرفة هذه للحصول على معلومات جديدة. بالإضافة إلى ذلك ، نفترض أنه سيتم تحديثه بانتظام ، على سبيل المثال ، عن طريق إضافة إصدارات جديدة أو تحديث أعضاء المجموعة.

التخصيص


كما هو متوقع ، يعد تثبيت Amazon Neptune أمرًا سهلاً. تم توثيقه بشيء من التفصيل . يمكنك بدء قاعدة بيانات الرسم البياني ببضع نقرات. ومع ذلك ، عندما يتعلق الأمر بتكوين أكثر تفصيلاً ، يصعب العثور على المعلومات التي تحتاج إليها . لذلك ، نريد أن نشير إلى معلمة تكوين واحدة.


توضح لقطة شاشة التكوين لمجموعات معلمات

أمازون أن نبتون يركز على أعباء عمل المعاملات منخفضة الكمون ، وبالتالي فإن المهلة الافتراضية هي 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"
 
}'

لتجنب هذه العملية الطويلة في كل مرة نطلق فيها Neptune ، قررنا استعادة المثيل من اللقطة التي تم تحميل هذه الثلاثيات فيها بالفعل. البدء من لقطة أسرع بكثير ، ولكن لا يزال يستغرق حوالي ساعة حتى يتوفر نبتون للطلبات.

عند تحميل ثلاث مرات في البداية في نبتون ، واجهنا أخطاء مختلفة.

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

كان بعضها أخطاء في التحليل ، كما هو موضح أعلاه. حتى الآن ، ما زلنا لم نكتشف بالضبط الخطأ الذي حدث في هذه اللحظة. مزيد من التفاصيل سيساعد بالتأكيد هنا. حدث هذا الخطأ لحوالي 1٪ من الثلاثيات المدرجة. ولكن فيما يتعلق باختبار نبتون ، فقد قبلنا حقيقة أننا نعمل فقط مع 99٪ من المعلومات من MusicBrainz.

حتى إذا كان الأمر سهلاً بالنسبة للأشخاص المطلعين على SPARQL ، ضع في اعتبارك أنه يجب وضع تعليقات ثلاثية على RDF مع أنواع بيانات صريحة ، والتي يمكن أن تسبب أخطاء مرة أخرى.

جاري التحميل


كما ذكرنا أعلاه ، لا نريد استخدام نبتون كمستودع بيانات ثابت ، بل كقاعدة معرفية مرنة ومتطورة. لذلك ، كنا بحاجة إلى إيجاد طرق لتقديم ثلاثيات جديدة عند تغيير قاعدة المعرفة ، على سبيل المثال ، عندما يتم نشر ألبوم جديد أو عندما نريد تجسيد المعرفة المشتقة.

يدعم Neptune مشغلي المدخلات عبر استعلامات SPARQL ، سواء مع البيانات الأولية أو بناءً على عينات. سنناقش كلا النهجين أدناه.

كان أحد أهدافنا إدخال البيانات في وضع الدفق. خذ بعين الاعتبار إصدار ألبوم في بلد جديد. من وجهة نظر MusicBrainz ، هذا يعني أنه بالنسبة لإصدار يتضمن ألبومات وأغانٍ فردية و EPs وما إلى ذلك ، يتم إضافة سجل جديد إلى جدول بلد الإصدار. في 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
 
}

تستغرق إضافة ثلاث مرات مفردة إلى الرسم البياني عدة مللي ثانية ، بينما يعتمد وقت التنفيذ لإدراج نتيجة استعلام فرعي على وقت تنفيذ الاستعلام الفرعي نفسه.

على الرغم من حقيقة أننا لم نستخدمها كثيرًا ، يتيح لك Neptune أيضًا حذف ثلاثيات استنادًا إلى عينات أو بيانات صريحة يمكن استخدامها لتحديث المعلومات.

استعلامات SPARQL


عند تقديم العينة الفرعية السابقة ، والتي تُرجع عدد الإصدارات لكل فنان ، قدمنا ​​بالفعل النوع الأول من الطلبات التي نريد الإجابة عليها باستخدام Neptune. من السهل إنشاء استعلام في نبتون - أرسل طلب POST إلى نقطة نهاية SPARQL ، كما هو موضح أدناه:

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

نظرًا لتعقيد مثل هذا الطلب ، يمكننا فقط إجراء استعلامات نقطية لفنان معين ، مثل Elton John ، ولكن ليس لجميع الفنانين. لا يبدو أن نبتون يحسن مثل هذا الاستعلام بحذف الفلاتر في الأمثلة الفرعية. لذلك ، يجب تصفية كل عينة يدويًا باسم الفنان.

يمتلك نبتون كل ساعة ويدفع مقابل كل عملية إدخال / إخراج. لاختبارنا ، استخدمنا أصغر نسخة من نبتون ، والتي تكلف 0.384 دولار / ساعة. في حالة الطلب أعلاه ، الذي يحسب الملف الشخصي لفنان واحد ، ستقوم أمازون بتحصيل عشرات الآلاف من I / O ، مما يعني تكلفة 0.02 دولار.

استنتاج


أولاً ، يحافظ Amazon Neptune على معظم وعوده. كونها خدمة مُدارة ، فهي قاعدة بيانات للرسم البياني سهلة التركيب للغاية ويمكن إطلاقها بدون الكثير من الإعدادات. فيما يلي النتائج الرئيسية الخمسة التي توصلنا إليها:

  • التحميل المجمع بسيط ولكنه بطيء. ولكن يمكن أن يكون الأمر معقدًا بسبب رسائل الخطأ التي لا تساعد كثيرًا
  • دعم تحميل التدفق كل ما كنا نتوقعه ، وكان سريعًا بما يكفي
  • الاستعلامات بسيطة ولكنها ليست تفاعلية بما يكفي لإجراء استعلامات تحليلية
  • يجب تحسين استعلامات SPARQL يدويًا
  • من الصعب تقييم مدفوعات أمازون لأنه من الصعب تقدير كمية البيانات الممسوحة ضوئيًا بواسطة استعلام SPARQL.

هذا كل شئ. قم بالتسجيل في ندوة مجانية حول موضوع "موازنة التحميل" .

All Articles