如何使用 FILTER (?id IN ( … ) ) 来改善慢查询

3

我刚刚开始使用SPARQL,正在尝试创建一个查询,以检索所有信息,其中ID具有多个预定义值之一。我的查询代码类似于:

SELECT *
WHERE {
    ?id ?property ?value .
    ?value a ?type .
    ?type rdfs:label ?type_value .
    FILTER ( ?id IN (<id1>,<idi>,<idn> ) )
}

我遇到的问题是在id列表变得越来越大时,查询速度会变得非常缓慢。我直觉上认为有更好的方法来编写这个查询语句,但我很难找出如何创建这种查询语句。我考虑采用类似以下方式的解决方案:
SELECT * 
WHERE {
    <id_value> ?property ?value .
    ?value a ?type .
    ?type rdfs:label ?type_value .
}

我希望查询可以检索多个id的所有值,而不是在最后过滤结果,但我不知道如何编写查询来返回一个id_value的所有值。当我添加另一行用于另一个id_value时,它会过滤掉我期望的其他值,所以我认为我写得不正确。请问该如何操作?


看起来我最终将能够升级到virtuoso v.7,所以一旦我能获得升级,我会尝试这种方法。谢谢大家。我会在升级后发布我的发现! - rcheuk
谢谢大家!Values子句产生了巨大的影响——一个14秒的查询时间缩短到2-4秒。(仍在寻找优化的方法,现在正在查看Virtuoso设置,看看是否有可以改变以加快速度的地方,但这非常有前途!) - rcheuk
2个回答

5
使用values,您可以编写:
SELECT * WHERE {
  values ?id { <id1> <idi> <idn> }
  ?id ?property ?value .
  ?value a ?type .
  ?type rdfs:label ?type_value .
}

SPARQL 1.1关于values的说明:

数据可以直接写入图案或使用VALUES添加到查询中。VALUES提供内联数据作为解决方案序列,这些序列通过联接操作与查询评估结果相结合。它可被应用程序用来提供对查询结果的特定要求,也可被提供服务关键字进行联合查询的SPARQL查询引擎实现使用,以向远程查询服务发送更受限制的查询。

其中一个示例实际上与您已经得到的非常接近:

PREFIX dc:   <http://purl.org/dc/elements/1.1/> 
PREFIX :     <http://example.org/book/> 
PREFIX ns:   <http://example.org/ns#> 

SELECT ?book ?title ?price
{
   VALUES ?book { :book1 :book3 }
   ?book dc:title ?title ;
         ns:price ?price .
}

谢谢...不幸的是,我正在使用的当前sparql端点(virtuoso 6.1.6)不支持该子句。我想我会看看能否升级... - rcheuk
@harmlessdragon 嗯,这确实让事情变得更加复杂了。虽然这会使您的“查询”更长,但您能否尝试使用{ <id1> ... } union ... union { <idn> ... }来进行比较,并查看其性能如何?尽管它在文本上会更长,但性能应该会更好,因为您只会得到想要的结果。 - Joshua Taylor
已经尝试过那个方法哈哈...结果比使用“FILTER”子句还要长一些。 - rcheuk
@harmlessdragon 噢,那真是痛苦。:( - Joshua Taylor

2

尝试使用VALUES子句,如下所示:

SELECT * 
WHERE {
    VALUES ?id { ...list of ids... }
    ?id ?property ?value .
    ?value a ?type .
    ?type rdfs:label ?type_value .
}

使用这种方法应该比使用FILTER方法更加高效。


这个答案的一些评论中,我们(你和我)对于FILTER( ?document = ... || ?document = ... )被优化为基于union的查询进行了一些讨论(但我认为其中一个评论已经被删除了)。是否有任何理由认为?id in ( ... )不应该以同样的方式进行优化? - Joshua Taylor
我之前遇到了values子句。不幸的是,我正在使用的当前sparql端点(virtuoso 6.1.6)不支持该子句。我想我得看看能否升级一下... - rcheuk
@JoshuaTaylor 在ARQ中,?id IN ( )会被转换为等效的?id == <x> || ?id == <y>等形式,然后再转换为UNION。但是优化器在行为上会有很大的差异,特别是在像Virtuoso这样将SPARQL编译成SQL的情况下。 - RobV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接