【发布时间】:2021-10-24 08:28:52
【问题描述】:
我有一个用 SPARQL 进行的复合“搜索”查询
(1) 搜索特定 rdf:type 的唯一主题 URI:
例子:
SELECT ?s FROM NAMED <http://www.example.org/graph1> FROM NAMED <http://www.example.org/graph2>
{
GRAPH ?g
{
?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.org/widget>.
}
} OFFSET 10000 LIMIT 100
这个查询非常简单,只返回“widget”类型的所有主题。
(2)对于返回的满足主题URI的页面,搜索所有对这些主题URI有引用的主题URI(即引用实体),指定引用谓词URI表示引用。
假设前面的查询 (1) 返回了 2 个主题 URI http://www.example.org/widget100 和 http://www.example.org/widget101,而我要查询的引用谓词是 http://www.example.org/widget:
例子:
SELECT ?s FROM NAMED <http://www.example.org/graph1> FROM NAMED <http://www.example.org/graph2>
WHERE {
UNION
{
?s <http://www.example.org/widget> <http://www.example.org/widget100>
}
UNION
{
?s <http://www.example.org/widget> <http://www.example.org/widget101>
}
}
如果上一页返回 100 个主题 URI,则此处每个主题将有 100 个“UNION”语句。
此查询有效 - 它选择给定类型的主题 URI,并返回使用给定引用谓词引用这些主题的附加主题 URI。
问题出在实践中,当我的查询图中有 100,000 个三元组时,即使在内存图上的快速机器上,此查询通常也需要 1 分钟以上的时间才能执行。对于这种相当典型的搜索场景,这对于用户来说速度太慢了。
在分析下,两个查询都占用大约 50% 的查询时间。
我有足够的 SPARQL 经验来构造上面的这样一个查询,但我当然不是专家。我想知道这是否可以提高效率。例如,它是否可以组合成一个查询,至少可以将查询时间减少 50% 以上?是否可以通过更有效的方法替代我在潜在的许多主题中使用 UNION?
谢谢
SPARQL 家伙
更新:我已设法将查询缩减为以下形式的单个查询:
SELECT *
FROM NAMED <http://www.example.org/widgets>
FROM NAMED <http://www.example.org/widgetstats>
FROM NAMED <http://www.example.org/widgetmetadata>
FROM NAMED <http://www.example.org/widgetfactory>
WHERE
{ { SELECT ?s ?p ?o
WHERE
{ GRAPH ?g
{ ?s ?p ?o }
{ SELECT ?s
WHERE
{ GRAPH ?i
{ ?s a <http://www.example.org/widget> }
}
OFFSET 0
LIMIT 100
}
}
}
UNION
{ SELECT ?s ?p ?o
WHERE
{ GRAPH ?g
{ ?s ?p ?o }
{ SELECT DISTINCT ?s
WHERE
{ GRAPH ?h
{ OPTIONAL
{ ?s <http://www.example.org/widgetstats/widget> ?x }
OPTIONAL
{ ?s <http://www.example.org/widgetmetadata/widget> ?x }
OPTIONAL
{ ?s <http://www.example.org/widgetfactory/widget> ?x }
}
{ SELECT ?x
WHERE
{ GRAPH ?i
{ ?x a <http://www.example.org/widget> }
}
OFFSET 0
LIMIT 100
}
}
}
}
}
}
这将查询速度提高了大约。 50%。不过,我认为查询可以更快。这种查询形式 - 首先获取与给定类型的主要实体关联的所有三元组,然后是与引用实体关联的所有三元组 - 需要两个相同的最内层子查询,获取给定类型的唯一主题。
有没有什么办法可以减少这个查询——也许用一个查询而不是两个子查询的 UNION 来执行?我假设这可能会进一步提高性能。
更新 2:我无法改进上面的查询(第一次更新),所以我现在将其作为答案。
【问题讨论】:
-
如果将这两个查询结合起来会发生什么?
SELECT ?s { GRAPH <http://www.example.org/graph1> { ?type <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.org/widget> . ?s <http://www.example.org/widget> ?type . } GRAPH <http://www.example.org/graph2> { ?type <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.org/widget> . ?s <http://www.example.org/widget> ?type . } } -
你也可以让它更紧凑:
SELECT ?s WHERE { VALUES ?g { <http://www.example.org/graph1> <http://www.example.org/graph2> } GRAPH ?g { ?type rdf:type <http://www.example.org/widget> . ?s <http://www.example.org/widget> ?type } }
标签: sparql