Ấn tượng đầu tiên về Amazon Neptune

Xin chào cư dân Khabrovsk. Trong sự chờ đợi sự bắt đầu của khóa học "AWS dành cho nhà phát triển" Chúng tôi đã chuẩn bị một bản dịch tài liệu thú vị.

Ấn tượng đầu tiên về Amazon Neptune

Trong nhiều trường hợp sử dụng mà chúng tôi thích dữ liệu bakdataNhư chúng tôi thấy trên trang web của khách hàng, thông tin liên quan bị ẩn trong các kết nối giữa các thực thể, chẳng hạn như khi phân tích mối quan hệ giữa người dùng, sự phụ thuộc giữa các thành phần hoặc kết nối giữa các cảm biến. Các trường hợp sử dụng như vậy thường được mô hình hóa trên biểu đồ. Đầu năm nay, Amazon đã phát hành cơ sở dữ liệu đồ thị mới, Neptune. Trong bài đăng này, chúng tôi muốn chia sẻ những ý tưởng đầu tiên, những phương pháp hay và những gì có thể được cải thiện theo thời gian.

Tại sao chúng tôi cần Amazon Neptune

Cơ sở dữ liệu đồ thị hứa hẹn sẽ xử lý các tập dữ liệu có tính kết nối cao tốt hơn so với các tập dữ liệu quan hệ tương đương của chúng. Trong các tập dữ liệu như vậy, thông tin liên quan thường được lưu trữ trong mối quan hệ giữa các đối tượng. Chúng tôi đã sử dụng một dự án dữ liệu mở tuyệt vời để kiểm tra Neptune Âm nhạcBrainz. MusicBrainz thu thập mọi loại siêu dữ liệu âm nhạc có thể tưởng tượng được, chẳng hạn như thông tin về nghệ sĩ, bài hát, bản phát hành album hoặc buổi hòa nhạc cũng như nghệ sĩ đằng sau bài hát đó đã hợp tác với ai hoặc thời điểm album được phát hành ở quốc gia nào. MusicBrainz có thể được coi là một mạng lưới khổng lồ gồm các thực thể có mối liên hệ nào đó với ngành công nghiệp âm nhạc.

Tập dữ liệu MusicBrainz được cung cấp dưới dạng kết xuất CSV của cơ sở dữ liệu quan hệ. Tổng cộng, kết xuất chứa khoảng 93 triệu hàng trong 157 bảng. Mặc dù một số bảng này chứa dữ liệu cơ bản như nghệ sĩ, sự kiện, bản ghi âm, bản phát hành hoặc bản nhạc, những bảng khác bảng liên kết — lưu trữ mối quan hệ giữa nghệ sĩ và bản ghi âm, nghệ sĩ hoặc bản phát hành khác, v.v... Chúng thể hiện cấu trúc biểu đồ của một tập dữ liệu. Khi chuyển đổi tập dữ liệu thành bộ ba RDF, chúng tôi đã thu được khoảng 500 triệu phiên bản.

Dựa trên kinh nghiệm và ấn tượng của các đối tác dự án mà chúng tôi làm việc cùng, chúng tôi trình bày một bối cảnh trong đó cơ sở kiến ​​thức này được sử dụng để thu thập thông tin mới. Ngoài ra, chúng tôi hy vọng nó sẽ được cập nhật thường xuyên, chẳng hạn như bằng cách thêm các bản phát hành mới hoặc cập nhật thành viên nhóm.

điều chỉnh

Đúng như mong đợi, việc cài đặt Amazon Neptune rất đơn giản. Cô ấy khá chi tiết được ghi lại. Bạn có thể khởi chạy cơ sở dữ liệu đồ thị chỉ bằng vài cú nhấp chuột. Tuy nhiên, khi nói đến cấu hình chi tiết hơn, thông tin cần thiết khó khăn để tìm thấy. Vì vậy, chúng tôi muốn trỏ đến một tham số cấu hình.

Ấn tượng đầu tiên về Amazon Neptune
Ảnh chụp màn hình cấu hình cho các nhóm tham số

Amazon cho biết Neptune tập trung vào khối lượng công việc giao dịch có độ trễ thấp, đó là lý do tại sao thời gian chờ yêu cầu mặc định là 120 giây. Tuy nhiên, chúng tôi đã thử nghiệm nhiều trường hợp sử dụng phân tích và thường xuyên đạt đến giới hạn này. Thời gian chờ này có thể được thay đổi bằng cách tạo nhóm tham số mới cho Neptune và cài đặt neptune_query_timeout hạn chế tương ứng.

Đang tải dữ liệu

Dưới đây chúng tôi sẽ thảo luận chi tiết về cách chúng tôi tải dữ liệu MusicBrainz vào Neptune.

Mối quan hệ theo bộ ba

Đầu tiên, chúng tôi chuyển đổi dữ liệu MusicBrainz thành bộ ba RDF. Do đó, đối với mỗi bảng, chúng tôi đã xác định một mẫu xác định cách thể hiện mỗi cột trong bộ ba. Trong ví dụ này, mỗi hàng từ bảng biểu diễn được ánh xạ tới XNUMX bộ ba 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> .

tải lên hàng loạt

Cách được đề xuất để tải lượng lớn dữ liệu vào Neptune là thông qua quy trình tải lên hàng loạt qua S3. Sau khi tải các tệp bộ ba lên S3, bạn bắt đầu tải lên bằng yêu cầu POST. Trong trường hợp của chúng tôi, phải mất khoảng 24 giờ cho 500 triệu cặp sinh ba. Chúng tôi mong đợi nó sẽ nhanh hơn.

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

Để tránh quá trình kéo dài này mỗi khi khởi chạy Neptune, chúng tôi đã quyết định khôi phục phiên bản từ ảnh chụp nhanh trong đó các bộ ba này đã được tải. Chạy từ ảnh chụp nhanh nhanh hơn đáng kể nhưng vẫn mất khoảng một giờ cho đến khi Neptune sẵn sàng nhận yêu cầu.

Khi lần đầu tải bộ ba vào Neptune, chúng tôi đã gặp nhiều lỗi khác nhau.

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

Một số trong số đó là lỗi phân tích cú pháp, như được hiển thị ở trên. Cho đến nay, chúng tôi vẫn chưa tìm ra chính xác điều gì đã xảy ra vào thời điểm này. Một chút chi tiết chắc chắn sẽ giúp ích ở đây. Lỗi này xảy ra với khoảng 1% số bộ ba được chèn. Nhưng khi thử nghiệm Neptune, chúng tôi chấp nhận thực tế là chúng tôi chỉ làm việc với 99% thông tin từ MusicBrainz.

Mặc dù điều này dễ dàng đối với những người quen thuộc với SPARQL, hãy lưu ý rằng bộ ba RDF phải được chú thích bằng các kiểu dữ liệu rõ ràng, điều này một lần nữa có thể gây ra lỗi.

Tải xuống trực tuyến

Như đã đề cập ở trên, chúng tôi không muốn sử dụng Neptune như một kho lưu trữ dữ liệu tĩnh mà là một cơ sở kiến ​​thức linh hoạt và đang phát triển. Vì vậy, chúng tôi cần tìm cách giới thiệu các bộ ba mới khi nền tảng kiến ​​thức thay đổi, chẳng hạn như khi một album mới được xuất bản hoặc khi chúng tôi muốn hiện thực hóa kiến ​​thức rút ra.

Neptune hỗ trợ các toán tử đầu vào thông qua các truy vấn SPARQL, cả dựa trên mẫu và dựa trên mẫu. Chúng tôi sẽ thảo luận về cả hai cách tiếp cận dưới đây.

Một trong những mục tiêu của chúng tôi là nhập dữ liệu theo cách truyền phát. Hãy cân nhắc việc phát hành album ở một quốc gia mới. Theo quan điểm của MusicBrainz, điều này có nghĩa là đối với một bản phát hành bao gồm album, đĩa đơn, EP, v.v., một mục mới sẽ được thêm vào bảng nước phát hành. Trong RDF, chúng tôi khớp thông tin này với hai bộ ba mới.

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

Một mục tiêu khác là thu được kiến ​​thức mới từ biểu đồ. Giả sử chúng ta muốn biết số lượng bản phát hành mà mỗi nghệ sĩ đã xuất bản trong sự nghiệp của họ. Một truy vấn như vậy khá phức tạp và mất hơn 20 phút trong Neptune, vì vậy chúng ta cần cụ thể hóa kết quả để sử dụng lại kiến ​​thức mới này trong một số truy vấn khác. Vì vậy, chúng tôi thêm các bộ ba có thông tin này trở lại biểu đồ, nhập kết quả của truy vấn phụ.

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
 
}

Việc thêm các bộ ba đơn lẻ vào biểu đồ mất vài mili giây, trong khi thời gian thực hiện để chèn kết quả của truy vấn con phụ thuộc vào thời gian thực hiện của chính truy vấn con đó.

Mặc dù chúng tôi không sử dụng nó thường xuyên nhưng Neptune cũng cho phép bạn xóa các bộ ba dựa trên các mẫu hoặc dữ liệu rõ ràng, những dữ liệu này có thể được sử dụng để cập nhật thông tin.

Truy vấn SPARQL

Bằng cách giới thiệu mẫu phụ trước đó, mẫu này trả về số lượng bản phát hành của mỗi nghệ sĩ, chúng tôi đã giới thiệu loại truy vấn đầu tiên mà chúng tôi muốn trả lời bằng cách sử dụng Neptune. Việc xây dựng truy vấn trong Neptune thật dễ dàng - gửi yêu cầu POST tới điểm cuối SPARQL, như hiển thị bên dưới:

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

Ngoài ra, chúng tôi đã triển khai truy vấn trả về hồ sơ nghệ sĩ chứa thông tin về tên, tuổi hoặc quốc gia xuất xứ của họ. Hãy nhớ rằng người biểu diễn có thể là cá nhân, ban nhạc hoặc dàn nhạc. Ngoài ra, chúng tôi bổ sung dữ liệu này với thông tin về số lượng bản phát hành của các nghệ sĩ trong năm. Đối với các nghệ sĩ solo, chúng tôi cũng bổ sung thêm thông tin về ban nhạc mà nghệ sĩ đó tham gia mỗi năm.

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

Do tính phức tạp của truy vấn như vậy, chúng tôi chỉ có thể thực hiện truy vấn điểm cho một nghệ sĩ cụ thể, chẳng hạn như Elton John, chứ không phải cho tất cả các nghệ sĩ. Neptune dường như không tối ưu hóa truy vấn như vậy bằng cách thả các bộ lọc vào các phần chọn phụ. Vì vậy, mỗi lựa chọn phải được lọc thủ công theo tên nghệ sĩ.

Neptune có cả phí theo giờ và phí theo I/O. Để thử nghiệm, chúng tôi đã sử dụng phiên bản Neptune ở mức tối thiểu, có giá 0,384 USD/giờ. Trong trường hợp truy vấn ở trên tính toán hồ sơ cho một nhân viên, Amazon tính phí cho chúng tôi hàng chục nghìn thao tác I/O, tức là chi phí là 0.02 USD.

Đầu ra

Đầu tiên, Amazon Neptune giữ hầu hết những lời hứa của mình. Là một dịch vụ được quản lý, đây là một cơ sở dữ liệu đồ thị cực kỳ dễ cài đặt và có thể thiết lập và chạy mà không cần nhiều cấu hình. Dưới đây là năm phát hiện chính của chúng tôi:

  • Tải lên hàng loạt dễ dàng nhưng chậm. Nhưng nó có thể trở nên phức tạp với các thông báo lỗi không hữu ích lắm.
  • Tải xuống trực tuyến hỗ trợ mọi thứ chúng tôi mong đợi và khá nhanh
  • Các truy vấn đơn giản nhưng không đủ tính tương tác để chạy các truy vấn phân tích
  • Truy vấn SPARQL phải được tối ưu hóa theo cách thủ công
  • Khó ước tính các khoản thanh toán của Amazon vì khó ước tính lượng dữ liệu được truy vấn SPARQL quét.

Đó là tất cả. Đăng ký cho hội thảo trực tuyến miễn phí về chủ đề “Cân bằng tải”.


Nguồn: www.habr.com

Thêm một lời nhận xét