4

SPARQLを使用してトリプルストアからいくつかのユーザー統計を生成しようとしています。以下のクエリを参照してください。これをどのように改善できますか?私はここで何か悪いことをしていますか?なぜこれほど多くのメモリを消費するのですか?(この投稿の最後にある背景記事を参照してください)

私は、トリプルストア内ですべての集約と結合を行うことを好みます。クエリを分割すると、データベースの外部で結果を「手動で」結合する必要があり、トリプルストアの効率と最適化が失われます。正当な理由もなく、車輪の再発明をする必要はありません。

クエリ

SELECT
    ?person
    (COUNT(DISTINCT ?sent_email) AS ?sent_emails)
    (COUNT(DISTINCT ?received_email) AS ?received_emails)
    (COUNT(DISTINCT ?receivedInCC_email) AS ?receivedInCC_emails)
    (COUNT(DISTINCT ?revision) AS ?commits)

WHERE {
  ?person rdf:type foaf:Person.

  OPTIONAL {
    ?sent_email rdf:type email:Email.
    ?sent_email email:sender ?person.
  }

  OPTIONAL {
    ?received_email rdf:type email:Email.
    ?received_email email:recipient ?person.
  }

  OPTIONAL {
    ?receivedInCC_email rdf:type email:Email.
    ?receivedInCC_email email:ccRecipient ?person.
  }

  OPTIONAL {
    ?revision rdf:type vcs:VcsRevision.
    ?revision vcs:committedBy ?person.
  }
}
GROUP BY ?person
ORDER BY DESC(?commits)

バックグラウンド

問題は、AllegroGraphで「QUERYMEMORY LIMITREACHED」というエラーが発生することです(関連するSOの質問も参照してください)。リポジトリには約200kのトリプルしか含まれていないため、約200kの入力ファイル(ntriples)に簡単に収まります。60 MBの場合、クエリ結果を実行するには4 GBを超えるRAMが必要であり、これは約2桁高くなります。

4

1 に答える 1

0

サブクエリで計算を分割してみてください。次に例を示します。

SELECT
    ?person
    (MAX(?sent_emails_) AS ?sent_emails_)
    (MAX(?received_emails_ AS ?received_emails_)
    (MAX(?receivedInCC_emails_ AS ?receivedInCC_emails_)
    (MAX(?commits_) AS ?commits)
WHERE {
  { 
   SELECT 
          ?person 
          (COUNT(DISTINCT ?sent_email) AS ?sent_emails_) 
          (0 AS ?received_emails_) 
          (0 AS ?commits_) 
   WHERE {
    ?sent_email rdf:type email:Email.
    ?sent_email email:sender ?person.
    ?person rdf:type foaf:Person.
   } GROUP BY ?person 
  } union {
     (similar pattern for the others)
     ....
  }
}
GROUP BY ?person
ORDER BY DESC(?commits)

目的は次のとおりです。

  • 集計のために処理する必要がある結果セットに膨大な数の行が生成されるのを避ける
  • パフォーマンスにも影響する OPTIONAL{} パターンの使用を避ける
于 2014-07-08T13:00:22.110 に答える