亞馬遜海王星的第一印象

致敬,哈布羅夫斯克居民。 期待課程的開始 “面向開發人員的 AWS” 我們準備了有趣材料的翻譯。

亞馬遜海王星的第一印象

在我們喜歡的許多用例中 巴克數據正如我們在客戶的網站上看到的那樣,相關資訊隱藏在實體之間的連接中,例如在分析使用者之間的關係、元素之間的依賴關係或感測器之間的連接時。 此類用例通常在圖表上建模。 今年早些時候,亞馬遜發布了新的圖形資料庫 Neptune。 在這篇文章中,我們希望分享我們的第一個想法、良好實踐以及隨著時間的推移可以改進的地方。

為什麼我們需要 Amazon Neptune

圖形資料庫有望比關係資料庫更好地處理高度連接的資料集。 在此類資料集中,相關資訊通常儲存在物件之間的關係中。 我們使用了一個令人驚嘆的開放資料專案來測試海王星 MusicBrainz的。 MusicBrainz 收集各種可以想像的音樂元數據,例如有關藝術家、歌曲、專輯發行或音樂會的信息,以及歌曲背後的藝術家與誰合作或專輯在哪個國家發行的時間。 MusicBrainz 可以被視為一個龐大的實體網絡,這些實體以某種方式與音樂產業相連。

MusicBrainz 資料集以關聯式資料庫的 CSV 轉儲形式提供。 轉儲總共包含 93 個表格中的約 157 萬行。 雖然其中一些表包含基本數據,例如藝術家、事件、錄音、發行或曲目,但其他表 連結表 — 儲存藝術家和唱片、其他藝術家或發行作品之間的關係…它們展示了資料集的圖形結構。 當將資料集轉換為 RDF 三元組時,我們獲得了大約 500 億個實例。

根據與我們合作的專案合作夥伴的經驗和印象,我們提出了一種使用該知識庫來獲取新資訊的設定。 此外,我們希望它能夠定期更新,例如新增版本或更新群組成員。

調整

如預期的那樣,安裝 Amazon Neptune 非常簡單。 她說的很詳細 記錄在案。 只需點擊幾下即可啟動圖形資料庫。 然而,當涉及到更詳細的配置時, 必要的資訊 很難找到。 因此,我們想要指向一個配置參數。

亞馬遜海王星的第一印象
參數組的配置螢幕截圖

亞馬遜表示,Neptune 專注於低延遲事務工作負載,這就是預設請求逾時為 120 秒的原因。 然而,我們測試了許多分析用例,在這些用例中我們經常達到這個限制。 可以透過為 Neptune 建立新參數組並設定來變更此逾時 neptune_query_timeout 相應的限制。

載入資料中

下面我們將詳細討論如何將 MusicBrainz 資料載入到 Neptune 中。

三人關係

首先,我們將 MusicBrainz 資料轉換為 RDF 三元組。 因此,對於每個表,我們定義了一個模板,用於定義如何在三元組中表示每一列。 在此範例中,表演者表中的每一行都會對應到 XNUMX 個 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> .

馬克魯茲卡

將大量資料載入到 Neptune 的建議方法是透過 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 時出現這個漫長的過程,我們決定從已載入這些三元組的快照中還原實例。 從快照運行的速度明顯更快,但仍需要大約一個小時才能讓 Neptune 滿足請求。

當最初將三元組載入到 Neptune 時,我們遇到了各種錯誤。

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

其中一些是解析錯誤,如上所示。 到目前為止,我們仍然沒有弄清楚到底出了什麼問題。 更詳細一點肯定會有所幫助。 大約 1% 的插入三元組出現此錯誤。 但就測試 Neptune 而言,我們接受了這樣一個事實:我們只使用來自 MusicBrainz 的 99% 的資訊。

儘管這對於熟悉 SPARQL 的人來說很容易,但請注意,RDF 三元組必須使用明確資料類型進行註釋,這又可能會導致錯誤。

串流媒體下載

如上所述,我們不想將 Neptune 用作靜態資料存儲,而是用作靈活且不斷發展的知識庫。 因此,當知識庫發生變化時,例如當新專輯發布或當我們想要具體化派生知識時,我們需要找到引入新三元組的方法。

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

另一個目標是從圖中獲得新知識。 假設我們想要獲得每位藝術家在其職業生涯中發行的作品數量。 這樣的查詢非常複雜,在 Neptune 中需要花費 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 回答的第一個查詢類型。 在 Neptune 中建立查詢非常簡單 - 向 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)
 
   }

由於此類查詢的複雜性,我們只能對特定藝術家(例如 Elton John)執行點查詢,而不能對所有藝術家執行點查詢。 海王星似乎沒有通過將過濾器放入子選擇中來優化此類查詢。 因此,每個選擇都必須按藝術家姓名手動過濾。

Neptune 按小時收費和按 I/O 收費。 在我們的測試中,我們使用了最低限度的 Neptune 實例,其成本為 0,384 美元/小時。 在上面的查詢中,計算單個工作人員的配置文件,Amazon 向我們收取數萬次 I/O 操作的費用,這意味著成本為 0.02 美元。

產量

首先,Amazon Neptune 兌現了大部分承諾。 作為託管服務,它是一個非常易於安裝的圖形資料庫,無需進行大量配置即可啟動和運行。 以下是我們的五個主要發現:

  • 批次上傳很簡單,但速度很慢。 但它可能會因為錯誤訊息而變得複雜,而這些錯誤訊息並不是很有幫助。
  • 串流媒體下載支援我們期望的一切並且速度相當快
  • 查詢很簡單,但互動性不足以執行分析查詢
  • SPARQL 查詢必須手動最佳化
  • 亞馬遜付款很難估計,因為很難估計 SPARQL 查詢掃描的資料量。

就這樣。 註冊 關於「負載平衡」主題的免費網路研討會.


來源: www.habr.com

添加評論