Kesan pertama Amazon Neptune

Salut, warga Khabrovsk. Untuk mengantisipasi dimulainya kursus "AWS untuk Pengembang" Kami telah menyiapkan terjemahan materi yang menarik.

Kesan pertama Amazon Neptune

Dalam banyak kasus penggunaan yang kami sukai bakdataSeperti yang kami lihat di situs web klien kami, informasi relevan disembunyikan dalam koneksi antar entitas, misalnya saat menganalisis hubungan antar pengguna, ketergantungan antar elemen, atau koneksi antar sensor. Kasus penggunaan seperti ini biasanya dimodelkan pada grafik. Awal tahun ini, Amazon merilis database grafik baru yang disebut Neptune. Dalam postingan ini kami ingin berbagi ide pertama kami, praktik baik, dan apa yang dapat ditingkatkan seiring berjalannya waktu.

Mengapa kami membutuhkan Amazon Neptune

Basis data grafik berjanji untuk menangani kumpulan data yang sangat terhubung dengan lebih baik daripada data relasionalnya. Dalam kumpulan data seperti itu, informasi yang relevan biasanya disimpan dalam hubungan antar objek. Kami menggunakan proyek data terbuka yang luar biasa untuk menguji Neptunus MusicBrainz. MusicBrainz mengumpulkan segala jenis metadata musik yang dapat dibayangkan, seperti informasi tentang artis, lagu, rilis album atau konser, serta dengan siapa artis di balik lagu tersebut berkolaborasi atau kapan album tersebut dirilis di negara mana. MusicBrainz dapat dilihat sebagai jaringan besar entitas yang terhubung dengan industri musik.

Kumpulan data MusicBrainz disediakan sebagai dump CSV dari database relasional. Secara total, dump tersebut berisi sekitar 93 juta baris di 157 tabel. Sementara beberapa tabel ini berisi data dasar seperti artis, acara, rekaman, rilis atau lagu, dan lainnya tabel tautan — menyimpan hubungan antara artis dan rekaman, artis atau rilisan lain, dll... Mereka mendemonstrasikan struktur grafik dari kumpulan data. Saat mengonversi kumpulan data menjadi RDF tiga kali lipat, kami memperoleh sekitar 500 juta instans.

Berdasarkan pengalaman dan kesan mitra proyek yang bekerja dengan kami, kami menyajikan lingkungan di mana basis pengetahuan ini digunakan untuk memperoleh informasi baru. Selain itu, kami mengharapkannya diperbarui secara berkala, misalnya dengan menambahkan rilis baru atau memperbarui anggota grup.

pengaturan

Seperti yang diharapkan, menginstal Amazon Neptune itu sederhana. Dia cukup detail didokumentasikan. Anda dapat meluncurkan database grafik hanya dengan beberapa klik. Namun, jika menyangkut konfigurasi yang lebih detail, informasi yang perlu sulit untuk ditemukan. Oleh karena itu, kami ingin menunjuk ke satu parameter konfigurasi.

Kesan pertama Amazon Neptune
Tangkapan layar konfigurasi untuk grup parameter

Amazon mengatakan Neptune berfokus pada beban kerja transaksional latensi rendah, itulah sebabnya batas waktu permintaan default adalah 120 detik. Namun, kami telah menguji banyak kasus penggunaan analitik di mana kami sering mencapai batas ini. Batas waktu ini dapat diubah dengan membuat grup parameter baru untuk Neptune dan pengaturannya neptune_query_timeout pembatasan yang sesuai.

Memuat Data

Di bawah ini kami akan membahas secara detail bagaimana kami memuat data MusicBrainz ke Neptune.

Hubungan bertiga

Pertama, kami mengubah data MusicBrainz menjadi tiga kali lipat RDF. Oleh karena itu, untuk setiap tabel, kami menentukan templat yang menentukan bagaimana setiap kolom direpresentasikan dalam triple. Dalam contoh ini, setiap baris dari tabel pemain dipetakan ke dua belas rangkap tiga 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> .

unggahan massal

Cara yang disarankan untuk memuat data dalam jumlah besar ke Neptune adalah melalui proses unggahan massal melalui S3. Setelah mengunggah file triples Anda ke S3, Anda mulai mengunggah menggunakan permintaan POST. Dalam kasus kami, diperlukan waktu sekitar 24 jam untuk 500 juta kembar tiga. Kami berharap ini bisa lebih cepat.

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

Untuk menghindari proses yang panjang ini setiap kali kami meluncurkan Neptune, kami memutuskan untuk memulihkan instance dari snapshot yang sudah memuat triplet ini. Menjalankan dari snapshot jauh lebih cepat, namun masih membutuhkan waktu sekitar satu jam hingga Neptune tersedia untuk permintaan.

Saat pertama kali memuat kembar tiga ke Neptunus, kami mengalami berbagai kesalahan.

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

Beberapa di antaranya adalah kesalahan penguraian, seperti yang ditunjukkan di atas. Sampai saat ini, kami masih belum menemukan apa yang sebenarnya salah pada saat ini. Sedikit lebih detail pasti akan membantu di sini. Kesalahan ini terjadi pada sekitar 1% dari tripel yang dimasukkan. Namun sejauh pengujian Neptune berjalan, kami menerima kenyataan bahwa kami hanya bekerja dengan 99% informasi dari MusicBrainz.

Meskipun hal ini mudah dilakukan bagi orang yang akrab dengan SPARQL, perlu diketahui bahwa RDF tripel harus dianotasi dengan tipe data eksplisit, yang lagi-lagi dapat menyebabkan kesalahan.

Unduhan streaming

Seperti disebutkan di atas, kami tidak ingin menggunakan Neptune sebagai penyimpanan data statis, melainkan sebagai basis pengetahuan yang fleksibel dan terus berkembang. Jadi kami perlu menemukan cara untuk memperkenalkan triplet baru ketika basis pengetahuan berubah, misalnya ketika album baru diterbitkan atau ketika kami ingin mewujudkan pengetahuan yang diperoleh.

Neptune mendukung operator masukan melalui kueri SPARQL, baik berbasis mentah maupun berbasis sampel. Kami akan membahas kedua pendekatan di bawah ini.

Salah satu tujuan kami adalah memasukkan data secara streaming. Pertimbangkan untuk merilis album di negara baru. Dari sudut pandang MusicBrainz, ini berarti bahwa untuk rilis yang mencakup album, single, EP, dll., entri baru ditambahkan ke tabel negara rilis. Di RDF, kami mencocokkan informasi ini dengan dua tripel baru.

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

Tujuan lainnya adalah untuk memperoleh pengetahuan baru dari grafik. Katakanlah kita ingin mengetahui jumlah rilisan yang diterbitkan setiap artis dalam kariernya. Kueri semacam itu cukup rumit dan memakan waktu lebih dari 20 menit di Neptunus, jadi kami perlu mewujudkan hasilnya agar dapat menggunakan kembali pengetahuan baru ini di kueri lainnya. Jadi kita menambahkan tiga kali lipat dengan informasi ini kembali ke grafik, memasukkan hasil subquery.

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
 
}

Menambahkan tripel tunggal ke grafik memerlukan waktu beberapa milidetik, sedangkan waktu eksekusi untuk memasukkan hasil subkueri bergantung pada waktu eksekusi subkueri itu sendiri.

Meskipun kami tidak sering menggunakannya, Neptune juga memungkinkan Anda menghapus kembar tiga berdasarkan sampel atau data eksplisit, yang dapat digunakan untuk memperbarui informasi.

Kueri SPARQL

Dengan memperkenalkan subsampel sebelumnya, yang mengembalikan jumlah rilis untuk setiap artis, kami telah memperkenalkan jenis kueri pertama yang ingin kami jawab menggunakan Neptune. Membuat kueri di Neptune itu mudah - kirim permintaan POST ke titik akhir SPARQL, seperti yang ditunjukkan di bawah ini:

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

Selain itu, kami telah menerapkan kueri yang mengembalikan profil artis yang berisi informasi tentang nama, usia, atau negara asal mereka. Ingatlah bahwa pemainnya bisa individu, band, atau orkestra. Selain itu, kami melengkapi data ini dengan informasi tentang jumlah rilisan yang dirilis oleh artis sepanjang tahun. Untuk artis solo, kami juga menambahkan informasi tentang band yang diikuti artis tersebut setiap tahunnya.

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

Karena kerumitan kueri tersebut, kami hanya dapat melakukan kueri titik untuk artis tertentu, seperti Elton John, namun tidak untuk semua artis. Neptune tampaknya tidak mengoptimalkan kueri seperti itu dengan memasukkan filter ke dalam subpilihan. Oleh karena itu, setiap pilihan harus difilter secara manual berdasarkan nama artis.

Neptunus memiliki biaya per jam dan per I/O. Untuk pengujian kami, kami menggunakan instance Neptune minimum, dengan biaya $0,384/jam. Dalam kasus kueri di atas, yang menghitung profil untuk satu pekerja, Amazon mengenakan biaya puluhan ribu operasi I/O, yang berarti biaya sebesar $0.02.

Keluaran

Pertama, Amazon Neptune menepati sebagian besar janjinya. Sebagai layanan terkelola, ini adalah database grafik yang sangat mudah dipasang dan dapat aktif dan berjalan tanpa banyak konfigurasi. Berikut adalah lima temuan utama kami:

  • Pengunggahan massal itu mudah namun lambat. Namun hal ini bisa menjadi rumit dengan pesan kesalahan yang tidak terlalu membantu.
  • Pengunduhan streaming mendukung semua yang kami harapkan dan cukup cepat
  • Kueri sederhana, namun tidak cukup interaktif untuk menjalankan kueri analitis
  • Kueri SPARQL harus dioptimalkan secara manual
  • Pembayaran Amazon sulit diperkirakan karena sulit memperkirakan jumlah data yang dipindai oleh kueri SPARQL.

Itu saja. Mendaftar untuk webinar gratis dengan topik “Load Balancing”.


Sumber: www.habr.com

Tambah komentar