在运行SPARQL查询和编写清理结果的代码之间存在权衡。
复杂查询: Pros:获得干净/高效的结果,清除Cons:超时错误的代码较少,处理时间较长。
我知道不能泛化它,但是想比较一下组合子查询(UNION,.)、过滤器和集合,看看哪个操作在超时的情况下是更昂贵的操作。
例如,我正在从日语SPARQL端点运行这个查询(我删除了其中的一些部分)。
SELECT ?film ?dblink ?filmType (group_concat(?actors ; separator = "|") AS ?actorset) (group_concat(?country ; separator = "|") AS ?countryset) (group_concat(?releaseDate ; separator = "|") AS ?releasedateset) (group_concat(?language ; separator = "|") AS ?languageset) (group_concat(?genre ; separator = "|") AS ?genreset) ?numberOfEpisodes ?numberOfSeasons
WHERE {
{?film a dbpedia-owl:Film } UNION {?film a dbpedia-owl:TelevisionShow } UNION {?film a dbpedia-owl:Cartoon } UNION {?film a dbpedia-owl:TelevisionSeason } .
{?film a ?filmType } .Filter(regex(?filmType,"(?:TelevisionSeason|Cartoon|Film|TelevisionShow)")) .
OPTIONAL { {?film dbpedia-owl:starring ?actors} UNION {?film dbpprop:starring ?actors} }. OPTIONAL { ?film dbpedia-owl:country ?country }. OPTIONAL { {?film dbpprop:genre ?genre} UNION { ?film dbpedia-owl:genre ?genre } }. OPTIONAL { {?film dbpprop:language ?language} UNION {?film dbpedia-owl:language ?language} }. OPTIONAL { ?film dbpedia-owl:wikiPageID ?wikiPageID } .
OPTIONAL {?film owl:sameAs ?dblink . Filter (strstarts( str(?dblink), 'http://dbpedia.org/resource/'))}
} LIMIT 5它超时了。在后面的代码中,有什么更有效(避免超时)来删除和处理结果?
1-聚集 (group_concat)
2-过滤器:在我的代码中处理它
3-子查询:删除一些子查询(可选vs Union)并在另一个查询中执行它们
发布于 2014-08-06 15:06:45
优化问题很难解决,特别是当端点可以施加不同的限制时。尽管如此,至少有一些东西可以大大简化这个查询。
寻找某些类别的个人
{?film a dbpedia-owl:Film } UNION {?film a dbpedia-owl:TelevisionShow } UNION {?film a dbpedia-owl:Cartoon } UNION {?film a dbpedia-owl:TelevisionSeason } .真正应该是:
values ?filmType { dbpedia-owl:Film
dbpedia-owl:Television
dbpedia-owl:Cartoon
dbpedia-owl:TelevisionSeason }
?film a ?filmType它将处理所有固定类型。下一部分
filter(regex(?filmType,"(?:TelevisionSeason|Cartoon|Film|TelevisionShow)"))似乎是为了找到包含这些字符串之一的任何类型。这可能需要迭代所有的个体,以及它们的所有类型,然后对它们运行一个正则表达式。呃。更好的方法是找到具有与这些内容相匹配的名称的本体类,然后检索这些类的个人。
(请注意,在这里和上面,卡通可能指的是非电影的东西,例如报纸上的政治漫画。)
尽管如此,更好的解决方案可能是浏览类层次结构,并查看是否有您感兴趣的事物的公共超类。如果某物是子类的成员,那么它也是超类的成员,所以您可以通过这种方式节省一些查询。
寻找可选属性
OPTIONAL { {?film dbpedia-owl:starring ?actors} UNION
{?film dbpprop:starring ?actors} } .
OPTIONAL { ?film dbpedia-owl:country ?country } .
OPTIONAL { {?film dbpprop:genre ?genre } UNION
{?film dbpedia-owl:genre ?genre } }.
OPTIONAL { {?film dbpprop:language ?language} UNION
{?film dbpedia-owl:language ?language} }.
OPTIONAL { ?film dbpedia-owl:wikiPageID ?wikiPageID } .要清理这些东西,你没什么可做的,只是:
匹配资源以给定的命名空间开始。
OPTIONAL { ?film owl:sameAs ?dblink .
Filter (strstarts( str(?dblink), 'http://dbpedia.org/resource/'))}这还不错,尽管owl:sameAs是传递性和自反性的,所以您可能应该让链接朝任何一个方向走。此外(这并不重要),通过使用str获取前缀,您可以使查询更易于维护。因此:
prefix dbpedia: <http://dbpedia.org/resource/>
optional { ?film (owl:sameAs|^owl:sameAs)* ?dblink .
filter (strstarts( str(?dblink), str(:dbpedia) ) }聚合函数
SELECT
?film ?dblink ?filmType
(group_concat(?actors ; separator = "|") AS ?actorset)
(group_concat(?country ; separator = "|") AS ?countryset)
(group_concat(?releaseDate ; separator = "|") AS ?releasedateset)
(group_concat(?language ; separator = "|") AS ?languageset)
(group_concat(?genre ; separator = "|") AS ?genreset)
?numberOfEpisodes ?numberOfSeasons
WHERE { … }
LIMIT 5您正在使用许多group_concat聚合。这本身可能不是什么问题,因为它只是遍历每个组并构建一个字符串。这是一个线性的结果(在小组之前),所以它不应该太昂贵。但是,同时选择组变量和非分组变量是不合法的。如果要选择5个没有聚合的变量,则需要显式地使用group:
SELECT
?film ?dblink ?filmType
(group_concat(?actors ; separator = "|") AS ?actorset)
(group_concat(?country ; separator = "|") AS ?countryset)
(group_concat(?releaseDate ; separator = "|") AS ?releasedateset)
(group_concat(?language ; separator = "|") AS ?languageset)
(group_concat(?genre ; separator = "|") AS ?genreset)
?numberOfEpisodes ?numberOfSeasons
WHERE { }
GROUP BY ?film ?dblink ?filmType ?numberOfEpisodes ?numberOfSeasons
LIMIT 5我知道Virtuoso可能接受没有显式组by的查询,但在SPARQL中它是必需的。事实上,我回答了answers.semanticweb.com最近的一个问题,变量已在范围内错误时使用。,它触及了这一点。在Spamql.org的验证器中检查查询是个好主意。
https://stackoverflow.com/questions/25161997
复制相似问题