可以使这个 SPARQL 搜索查询更有效率吗?
Can this SPARQL search query be made more efficient?
我有一个在 SPARQL 中进行的复合 'search' 查询
(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
这个查询非常简单,只是 returns 所有 'widget' 类型的主题。
(2) 对于满足主题URI的返回页面,搜索所有引用这些主题URI(即引用实体)的主题URI,指定指示引用的引用谓词URI。
假设之前的查询 (1) 返回了 2 个主题 URI http://www.example.org/widget100 and http://www.example.org/widget101 and the referencing predicate I wanted to query for was 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,以及 returns 使用给定引用谓词引用那些主题的附加主题 URI。
问题实际上是,当我的查询图中有 100,000 个三元组时,即使在内存图上的快速机器上,此查询通常也需要 1 分钟以上的时间来执行。对于这种相当典型的搜索场景,这对于用户来说太慢了。
根据分析,这两个查询大约占用查询时间的 50%。
我有足够的 SPARQL 经验来构建上面这样的查询,但我当然不是专家。我想知道是否可以提高效率。例如,是否可以将其组合成一个查询,至少可以将查询时间减少 50% 以上?我在潜在的许多主题中使用 UNION 是否可以用更有效的方法替换?
谢谢
SPARQL 专家
UPDATE:我已设法将查询减少为以下形式的单个查询:
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:我无法改进上面的查询(第一次更新),所以我暂时将其作为答案。
如果您仍然想要第一个查询的分页,那么最好的方法可能是使用 SPARQL subquery.
组合查询
请注意,对于子查询,您是从内向外工作的,因此子查询会选择小部件,而外部查询会展开以查找引用。如果您使用的是 FROM NAMED,那么您需要在图表上进行匹配(假设您的结果在命名图表中并且您没有使用联合默认图表)。内部查询中的 OFFSET 和 LIMIT 意味着下面的示例 returns 引用了第三个小部件(引擎应用的任何默认排序顺序)。
我不确定这是否会加快整体查询时间,但值得尝试并为您节省大量字符串连接!
PREFIX ex: <http://www.example.org/>
SELECT ?s FROM NAMED ex:g1 FROM NAMED ex:g2 WHERE {
GRAPH ?h {
?s ex:widget ?x
}
{
SELECT ?x WHERE {
GRAPH ?g {
?x a ex:widget
}
} OFFSET 2 LIMIT 1
}
}
我有一个在 SPARQL 中进行的复合 'search' 查询
(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
这个查询非常简单,只是 returns 所有 'widget' 类型的主题。
(2) 对于满足主题URI的返回页面,搜索所有引用这些主题URI(即引用实体)的主题URI,指定指示引用的引用谓词URI。
假设之前的查询 (1) 返回了 2 个主题 URI http://www.example.org/widget100 and http://www.example.org/widget101 and the referencing predicate I wanted to query for was 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,以及 returns 使用给定引用谓词引用那些主题的附加主题 URI。
问题实际上是,当我的查询图中有 100,000 个三元组时,即使在内存图上的快速机器上,此查询通常也需要 1 分钟以上的时间来执行。对于这种相当典型的搜索场景,这对于用户来说太慢了。
根据分析,这两个查询大约占用查询时间的 50%。
我有足够的 SPARQL 经验来构建上面这样的查询,但我当然不是专家。我想知道是否可以提高效率。例如,是否可以将其组合成一个查询,至少可以将查询时间减少 50% 以上?我在潜在的许多主题中使用 UNION 是否可以用更有效的方法替换?
谢谢
SPARQL 专家
UPDATE:我已设法将查询减少为以下形式的单个查询:
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:我无法改进上面的查询(第一次更新),所以我暂时将其作为答案。
如果您仍然想要第一个查询的分页,那么最好的方法可能是使用 SPARQL subquery.
组合查询请注意,对于子查询,您是从内向外工作的,因此子查询会选择小部件,而外部查询会展开以查找引用。如果您使用的是 FROM NAMED,那么您需要在图表上进行匹配(假设您的结果在命名图表中并且您没有使用联合默认图表)。内部查询中的 OFFSET 和 LIMIT 意味着下面的示例 returns 引用了第三个小部件(引擎应用的任何默认排序顺序)。
我不确定这是否会加快整体查询时间,但值得尝试并为您节省大量字符串连接!
PREFIX ex: <http://www.example.org/>
SELECT ?s FROM NAMED ex:g1 FROM NAMED ex:g2 WHERE {
GRAPH ?h {
?s ex:widget ?x
}
{
SELECT ?x WHERE {
GRAPH ?g {
?x a ex:widget
}
} OFFSET 2 LIMIT 1
}
}