我有一个 sparql-Query,它询问给定类型的 URI 的某些属性。由于我不确定这些属性是否存在,我使用 OPTIONAL 关键字:
PREFIX mbo: <http://creativeartefact.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT * WHERE {
?uri a mbo:LiveMusicEvent.
OPTIONAL {?uri rdfs:label ?label}.
OPTIONAL {?uri mbo:organisedBy ?organiser}.
OPTIONAL {?uri mbo:takesPlaceAt ?venue}.
OPTIONAL {?uri mbo:begin ?begin}.
OPTIONAL {?uri mbo:end ?end}.
}
当我对 SPARQL-Endpoint(Virtuoso 服务器)运行此查询时,出现错误:
Virtuoso 42000 Error The estimated execution time -721420288 (sec) exceeds the limit of 400 (sec).
当我减少 OPTIONAL 子句时,在第一个删除的子句之后,估计执行时间为 4106 秒,当我删除两个子句时,执行查询(并立即返回值)。
我不明白,为什么使用附加的 OPTIONAL 子句估计执行时间会像这样飙升,但也许我只是使用了错误的构造查询?
最佳答案
OPTIONAL 模式对于 SPARQL 引擎的评估(与“正常”连接模式相比)通常很昂贵。在这种情况下,错误表明 Virtuoso 的查询规划器估计查询过于复杂,无法在设定的时间限制内执行(请注意,它对此进行了估计 - 因此精确值可能是错误的)。
您有多种选择。不过,它们中的大多数都涉及执行多个查询。一个常见的模式是“检索和迭代”模式——首先进行一个查询,检索 mbo:LiveMusicEvent
的所有实例。 :
SELECT ?uri WHERE { ?uri a mbo:LiveMusicEvent }
然后迭代结果并检索每个实例的可选属性:
SELECT *
WHERE { VALUES(?uri) { <http://example.org/instance1> }
OPTIONAL {?uri rdfs:label ?label}.
OPTIONAL {?uri mbo:organisedBy ?organiser}.
OPTIONAL {?uri mbo:takesPlaceAt ?venue}.
OPTIONAL {?uri mbo:begin ?begin}.
OPTIONAL {?uri mbo:end ?end}.
}
如您所见,我使用了
VALUES
clause将第一个查询的实例 ID 结果插入到第二个查询中。在这个例子中,我假设你一个一个地迭代,因此对每个实例进行查询,但作为进一步的优化,你可能会修改将多个实例添加到 VALUES
中。一次性子句(显然不是所有的都一次,因为这会使查询与原始查询具有相同的复杂性)。顺便说一句,
VALUES
是 SPARQL 1.1 功能,我不确定 Virtuoso 是否支持它。如果没有,您可以通过使用 FILTER
来达到相同的效果。子句或仅“手动”替换所有出现的变量 ?uri
带有每次迭代的实例 ID。处理它的另一种方法是首先执行一个 CONSTRUCT 查询,从更大的源中检索相关的数据子集,然后使用该子集的可选项执行更复杂的查询。例如:
CONSTRUCT
WHERE {
?uri a mbo:LiveMusicEvent;
?p ?o .
}
将检索有关
LiveMusicEvent
的所有数据实例作为 RDF 图。将该图放入本地 RDF 模型(例如,如果您使用 Java,则为 Sesame 模型或内存存储库),并从那里进一步查询。
关于rdf - SPARQL 查询中 OPTIONAL 关键字的替代方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25609691/