【问题标题】:Can this SPARQL search query be made more efficient?这个 SPARQL 搜索查询可以变得更高效吗?
【发布时间】: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/widget100http://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 &lt;http://www.example.org/graph1&gt; { ?type &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; &lt;http://www.example.org/widget&gt; . ?s &lt;http://www.example.org/widget&gt; ?type . } GRAPH &lt;http://www.example.org/graph2&gt; { ?type &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; &lt;http://www.example.org/widget&gt; . ?s &lt;http://www.example.org/widget&gt; ?type . } }
  • 你也可以让它更紧凑:SELECT ?s WHERE { VALUES ?g { &lt;http://www.example.org/graph1&gt; &lt;http://www.example.org/graph2&gt; } GRAPH ?g { ?type rdf:type &lt;http://www.example.org/widget&gt; . ?s &lt;http://www.example.org/widget&gt; ?type } }

标签: sparql


【解决方案1】:

如果您仍然想要第一个查询的分页,那么最好的方法可能是使用 SPARQL subquery 组合查询。

请注意,子查询是从内向外工作的,因此子查询会选择小部件,而外部查询会展开以查找引用。如果您使用的是 FROM NAMED,那么您需要在图表上进行匹配(假设您的结果在命名图表中并且您没有使用联合默认图表)。内部查询上的 OFFSET 和 LIMIT 意味着下面的示例返回对第三个小部件的引用(以引擎应用的任何默认排序顺序)。

我不确定这是否会加快整体查询时间,但值得尝试并为您节省大量字符串连接!

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
  }
}

【讨论】:

  • 这确实显着改善了事情 - 作为一个粗略的基准,现在只需几分之一秒即可获得主题搜索页面,再加上外部查询中引用实体的主题标签与使用我之前的两个- 使用 UNION 的查询方法在相同负载下需要 12 秒左右。现在我要尝试做的是另外,一旦查询收集了所有这些主题,还有一个进一步的外部查询来获取这些主题的所有三元组(我正在使用 VALUES 说明符对所有这些主题执行的附加查询主题,大约需要 10 秒)。
  • 在基准测试下,我可以看到是基于 UNION 的第二个查询在消耗时间。删除此基于 UNION 的查询可显着节省性能。
猜你喜欢
  • 2013-02-10
  • 2012-01-14
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多