如何优化我的递归 SPARQL 查询?

Posted

技术标签:

【中文标题】如何优化我的递归 SPARQL 查询?【英文标题】:How can I optimize my recursive SPARQL query? 【发布时间】:2021-10-20 15:12:43 【问题描述】:

我正在尝试使用递归 SPARQL 查询从 Wikidata 中提取建筑物,但我不断收到查询超时。有没有办法绕过这个?

这是我当前的查询,选择所有具有 Freebase ID 或 Google Knowledge Graph ID 以及荷兰标签的建筑物:

SELECT DISTINCT ?building ?buildingLabel
WHERE 
  ?building p:P2671|p:P646 ?id;
            p:P31/ps:P31/wdt:P279* wd:Q41176;
            rdfs:label ?buildingLabel .
  FILTER(LANG(?buildingLabel) = 'nl') .
  FILTER (?building != ?buildingLabel) .

我尝试手动查看几层深度,但由于某种原因,我没有得到三层或更多层深度的结果,即使它们确实存在。我已经尝试过使用:

SELECT ?building
WHERE 
 ?building p:P31/ps:P31/wdt:P279 [p:P31/ps:P31/wdt:P279 [p:P31/ps:P31/wdt:P279 wd:Q41176]].

并使用

SELECT ?building
WHERE 
 ?parent2 p:P31/ps:P31/wdt:P279 wd:Q41176.
 ?parent1 p:P31/ps:P31/wdt:P279 ?parent2.
 ?building p:P31/ps:P31/wdt:P279 ?parent1.

在 Wikidata 上有大约 224 万座建筑物和大约 1800 万个具有 Freebase ID 或 Google Knowledge Graph ID 的实体。我查看了this guide,但不太清楚如何将其应用于我的查询。我也阅读了this question 的答案,但不幸的是,使用多个查询对我来说并不是一个真正的选择。

【问题讨论】:

p:P31/ps:P31/wdt:P279 [p:P31/ps:P31/wdt:P279 不等于 p:P31/ps:P31/wdt:P279*,因为 * 的优先级高于 / - 如果您希望在层次结构中最多三个跃点,则应使用 p:P31/ps:P31/wdt:P279?/wdt:P279?/wdt:P279? 【参考方案1】:

如果您的意图是使用“递归”属性路径来查找建筑物类型的事物以及作为建筑物子类的类型,那么您使用 wdt:P279* 的第一个查询是正确的,而后面的尝试重复完整的 p:P31/ps:P31/wdt:P279 模式将无法匹配任何数据。

通过稍微简化第一个查询,我能够让它运行(在 39 秒内返回 96,297 个结果):

SELECT DISTINCT ?building ?buildingLabel
WHERE 
  ?building p:P2671|p:P646 ?id;
            wdt:P31/wdt:P279* wd:Q41176 .
  ?building rdfs:label ?buildingLabel .
  FILTER(LANGMATCHES(LANG(?buildingLabel), "nl"))


两个显着变化:

p:P31/ps:P31wdt:P31 替换,从查询中删除一个连接。 第二个FILTER 是不必要的,因为?building(一个URI)和?buildingLabel(一个字符串)必然是不相等的

【讨论】:

以上是关于如何优化我的递归 SPARQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 SPARQL 查询超时以及如何优化这个查询?

知识图谱学习与实践——通过例句介绍Sparql的使用

递归 CTE 存在性能问题,需要建议以优化查询

如何将 Sparql 查询结果存储到数组中?

如何看待以及理解Python的这种尾递归优化

如何最简单的优化MySql