درود بر ساکنان خابروفسک. در آستانه شروع دوره
در بسیاری از موارد استفاده که ما دوست داریم
چرا ما به نپتون آمازون نیاز داشتیم؟
پایگاه داده های گراف قول می دهند که مجموعه داده های بسیار متصل را بهتر از معادل های رابطه ای خود مدیریت کنند. در چنین مجموعههای داده، اطلاعات مرتبط معمولاً در روابط بین اشیاء ذخیره میشوند. ما از یک پروژه داده باز شگفت انگیز برای آزمایش نپتون استفاده کردیم
مجموعه داده MusicBrainz به عنوان یک CSV dump از یک پایگاه داده رابطه ای ارائه شده است. در مجموع، این زباله حاوی حدود 93 میلیون ردیف در 157 جدول است. در حالی که برخی از این جداول حاوی دادههای اساسی مانند هنرمندان، رویدادها، ضبطها، انتشارات یا آهنگها هستند جداول پیوند - ذخیره روابط بین هنرمندان و ضبطها، سایر هنرمندان یا انتشارات، و غیره... آنها ساختار نمودار یک مجموعه داده را نشان میدهند. هنگام تبدیل مجموعه داده به سه گانه RDF، تقریباً 500 میلیون نمونه به دست آوردیم.
بر اساس تجربه و برداشت شرکای پروژه که با آنها کار می کنیم، محیطی را ارائه می دهیم که در آن از این پایگاه دانش برای به دست آوردن اطلاعات جدید استفاده می شود. علاوه بر این، ما انتظار داریم که به طور منظم به روز شود، به عنوان مثال با افزودن نسخه های جدید یا به روز رسانی اعضای گروه.
تنظیم
همانطور که انتظار می رفت، نصب آمازون نپتون ساده است. او کاملاً مفصل است
اسکرین شات پیکربندی برای گروه های پارامتر
آمازون می گوید که نپتون روی بارهای کاری تراکنش با تاخیر کم تمرکز دارد، به همین دلیل است که زمان درخواست پیش فرض ۱۲۰ ثانیه است. با این حال، بسیاری از موارد استفاده تحلیلی را آزمایش کردهایم که در آنها به طور مرتب به این حد رسیدهایم. با ایجاد یک گروه پارامتر جدید برای نپتون و تنظیم، می توان این زمان وقفه را تغییر داد 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٪ از سه گانه های درج شده رخ داده است. اما در مورد آزمایش نپتون، ما این واقعیت را پذیرفتیم که فقط با 99٪ از اطلاعات MusicBrainz کار می کنیم.
اگرچه این کار برای افرادی که با SPARQL آشنا هستند آسان است، اما توجه داشته باشید که سه گانه های RDF باید با انواع داده های صریح حاشیه نویسی شوند، که دوباره می تواند باعث خطا شود.
دانلود جریانی
همانطور که در بالا ذکر شد، ما نمی خواهیم از نپتون به عنوان یک ذخیره اطلاعات ثابت استفاده کنیم، بلکه می خواهیم به عنوان یک پایگاه دانش منعطف و در حال تکامل استفاده کنیم. بنابراین، زمانی که پایگاه دانش تغییر می کند، به عنوان مثال زمانی که یک آلبوم جدید منتشر می شود یا زمانی که می خواهیم دانش مشتق شده را به واقعیت تبدیل کنیم، باید راه هایی را برای معرفی سه گانه جدید پیدا کنیم.
نپتون از اپراتورهای ورودی از طریق کوئری های 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
}
افزودن سهگانههای منفرد به نمودار چند میلیثانیه طول میکشد، در حالی که زمان اجرا برای درج نتیجه یک پرسوجوی فرعی به زمان اجرای خود پرس و جو بستگی دارد.
اگرچه ما اغلب از آن استفاده نمیکردیم، اما Neptune همچنین به شما اجازه میدهد سهقلوها را بر اساس نمونهها یا دادههای صریح حذف کنید، که میتواند برای بهروزرسانی اطلاعات استفاده شود.
پرس و جوهای SPARQL
با معرفی زیرنمونه قبلی که تعداد انتشارات هر هنرمند را برمیگرداند، قبلاً اولین نوع کوئری را که میخواهیم با استفاده از نپتون به آن پاسخ دهیم، معرفی کردهایم. ایجاد یک پرس و جو در نپتون آسان است - مانند شکل زیر یک درخواست 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)
}
با توجه به پیچیدگی چنین پرس و جوی، ما فقط میتوانستیم برای یک هنرمند خاص، مانند التون جان، کوئریهای نقطهای را انجام دهیم، اما نه برای همه هنرمندان. به نظر نمی رسد که نپتون چنین پرس و جوی را با انداختن فیلترها در انتخاب های فرعی بهینه کند. بنابراین، هر انتخاب باید به صورت دستی بر اساس نام هنرمند فیلتر شود.
نپتون هم شارژ ساعتی و هم شارژ هر ورودی/خروجی دارد. برای آزمایش خود، از حداقل نمونه نپتون استفاده کردیم که هزینه آن 0,384 دلار در ساعت است. در مورد درخواست بالا، که نمایه یک کارگر را محاسبه میکند، آمازون دهها هزار عملیات ورودی/خروجی را از ما دریافت میکند که مستلزم هزینه 0.02 دلار است.
نتیجه
اول، آمازون نپتون به بیشتر وعده های خود عمل می کند. به عنوان یک سرویس مدیریت شده، این یک پایگاه داده گراف است که نصب آن بسیار آسان است و می تواند بدون تنظیمات زیادی راه اندازی و اجرا شود. در اینجا پنج یافته کلیدی ما آمده است:
- آپلود انبوه آسان اما کند است. اما ممکن است با پیام های خطایی که چندان مفید نیستند پیچیده شود.
- دانلود جریانی از همه چیزهایی که انتظار داشتیم پشتیبانی می کند و بسیار سریع بود
- کوئری ها ساده هستند، اما برای اجرای پرس و جوهای تحلیلی به اندازه کافی تعاملی نیستند
- پرس و جوهای SPARQL باید به صورت دستی بهینه شوند
- برآورد پرداختهای آمازون دشوار است، زیرا تخمین مقدار دادههای اسکن شده توسط یک پرس و جو SPARQL دشوار است.
همین. ثبت نام برای
منبع: www.habr.com