【问题标题】:Jena ARQ/TDB Query OptimizationJena ARQ/TDB 查询优化
【发布时间】:2013-08-29 17:17:27
【问题描述】:

我有一个相当小的图表,其中包含大约 50 万个三元组。我还生成了 stats.opt 文件并在相当快的计算机(四核、16gb 内存、ssd 驱动器)上运行我的代码。但是对于我在 OP 接口的帮助下构建的查询,它需要永远遍历结果集。结果集大约有15000行,迭代需要4s,这对于最终用户来说是无法接受的。执行查询只需要 90 毫秒(我猜真正的工作是由游标迭代完成的?)。为什么这么慢,我该怎么做才能加快结果集迭代?

这里是查询:

SELECT  ?apartment ?price ?hasBalcony ?lat ?long ?label ?hasImage ?park ?supermarket ?rooms ?area ?street
WHERE
  { ?apartment dssd:hasBalcony ?hasBalcony .
    ?apartment wgs84:lat ?lat .
    ?apartment wgs84:long ?long .
    ?apartment rdfs:label ?label .
    ?apartment dssd:hasImage ?hasImage .
    ?apartment dssd:hasNearby ?hasNearbyPark .
    ?hasNearbyPark dssd:hasNearbyPark ?park .
    ?apartment dssd:hasNearby ?hasNearbySupermarket .
    ?hasNearbySupermarket dssd:hasNearbySupermarket ?supermarket .
    ?apartment dssd:price ?price .
    ?apartment dssd:rooms ?rooms .
    ?apartment dssd:area ?area .
    ?apartment vcard:hasAddress ?address .
    ?address vcard:streetAddress ?street
    FILTER ( ?hasBalcony = true )
    FILTER ( ?price <= 1000.0e0 )
    FILTER ( ?price >= 650.0e0 )
    FILTER ( ?rooms <= 4.0e0 )
    FILTER ( ?rooms >= 3.0e0 )
    FILTER ( ?area <= 100.0e0 )
    FILTER ( ?area >= 60.0e0 )
  }    

(有没有更好的方法来查询这些 bnode:?hasNearbyPark, ?hasNearbySupermarket)

以及执行查询的代码:

dataset.begin(ReadWrite.READ);
Model model = dataset.getNamedModel("http://example.com");
QueryExecution queryExecution = QueryExecutionFactory.create(buildQuery(), model);
ResultSet resultSet = queryExecution.execSelect();
while ( resultSet.hasNext() ) {
    QuerySolution solution = resultSet.next(); ...

【问题讨论】:

  • 您可以将?apartment dssd:hasNearby [ dssd:hasNearbyPark ?park ]?apartment dssd:hasNearby [ dssd:hasNearbySupermarket ?supermarket ] 用于公园和超市,同样用于?address,除了获取?street 之外,您似乎不会使用它。您也可以使用; 节省大量输入。例如,而不是 ?apartment wgs84:lat ?lat . ?apartment wgs84:long ?long ., use ?apartment wgs84:lat ?lat ; wgs​​84:long ?long ; ...`。
  • 好吧,我正在使用 OP 以编程方式构建查询,所以我对此没有任何影响。这会改变执行时间吗?
  • 而不是FILTER ( ?hasBalcony = true ),您应该只使用?apartment dssd:hasBalcony true . 进行查询。如果您开始组合过滤器表达式,例如FILTER ( ?price &lt;= 1000.0e0 &amp;&amp; ?price &gt;= 650.0e0 ),是否有任何性能差异。另外,对于房间,如果这是一个整数值,也许你可以使用{?apt rooms 3} UNION {?apt rooms 4}
  • 空白节点语法是等价的。手写,空白节点语法可能更美观,但它的效率或多或少。 ; 的缩短也是如此。但是,使用union 而不是过滤器和hasBalcony true 而不是filter( hasBalcony = true ) 的 3 和 4 间房间可能会加快速度,因为它们会更多地限制匹配,并且过滤器会更少之后。同样,组合过滤器表达式可能会更好,但我不知道这是否已经自动发生。无论如何,这是值得尝试的。
  • 我刚刚尝试执行这样的查询:

标签: java sparql jena arq tdb


【解决方案1】:

在 ARQ 查询引擎上

首先,您似乎误解了 ARQ 引擎的工作原理:

ResultSet resultSet = queryExecution.execSelect();

以上所做的只是为引擎如何评估查询准备一个查询计划,它实际上并不评估查询,因此它几乎是即时的。

在您开始致电hasNext()next() 之前,不会进行实际回答您问题的工作:

while ( resultSet.hasNext() ) {
   QuerySolution solution = resultSet.next(); ...

所以你引用的时间不正确,查询需要 4 秒来评估,因为这是迭代所有结果所需的时间。

关于你的实际问题

您还没有展示您的buildQuery() 方法的作用,但您说您正在以编程方式将查询构建为Op 结构而不是字符串?如果是这种情况,那么查询引擎可能实际上并没有应用优化,尽管我不认为这将是问题。您可以在返回已构建的Op 之前尝试添加op = Algebra.optimize(op);,但我不知道这会产生多大的不同。

看起来优化器应该在给定原始查询的情况下做得很好(并不是说您的查询除了连接重新排序之外还有很多优化空间)但是如果您以编程方式构建它,那么您可能正在构建一个不寻常的代数,优化器正在苦苦挣扎。

同样,我不确定您的stats.opt 文件是否会受到尊重,因为您查询的是特定模型而不是 TDB 数据集,因此查询引擎可能是通用目的,而不是 TDB 引擎。我不是 TDB 方面的专家,所以我无法判断是否是这种情况。

底线

一般而言,您的问题中没有足够的信息来诊断您的设置中是否存在实际问题,或者您的查询是否非常昂贵。将此作为最小测试用例(最小完整代码加上示例数据)报告给 user@jena.apache.org 列表以进行进一步分析会很有用。

作为对您的查询的一般评论,许多范围过滤器的执行成本很高,这可能是大部分时间都在使用的地方。

【讨论】:

  • 感谢 Rob 的回答。在 arq 查询引擎上,我想的也差不多。在我的实际问题上,我尝试了 Algebra.optimize(op) 没有效果删除 stats.opt 也没有效果。删除 bnode 值 ?apartment dssd:hasNearby ?hasNearbyStop 。 ?hasNearbyStop dssd:hasNearbyStop ?stop 。 ?apartment dssd:hasNearby ?hasNearbySupermarket 。 ?hasNearbySupermarket dssd:hasNearbySupermarket ?supermarket .为我节省了将近 4 秒,所以这是最昂贵的部分。但是我仍然不敢相信这个查询在我极小的数据集上需要 4s(我不能公开)。
  • 因为我正在与 jena 合作,例如dbpedia(有更复杂的查询)很长时间了。
  • @DanielGerber 请记住,您对复杂查询和 ARQ 的概念不一定一致!通常使用 SPARQL,数据集的大小在很大程度上与性能无关,重要的是中间结果的大小。如果您至少可以发布您的 stats.opt 文件会很有趣,因为这将使我们了解您的数据集的特征,而不会泄露您的数据。
  • 澄清一下,数据集的大小与将产生的中间结果的大小以及回答查询所需的时间之间通常存在相关性。 然而无论数据集有多小,编写一个执行都非常糟糕的查询相对来说是微不足道的。相反,无论数据集有多大,编写一个总是非常快的查询。
  • 嘿@RobV,你能帮我澄清一下:模型是在RAM中还是通过硬盘执行查询(如果我像上面那样执行它)?如果是硬盘,我可以以某种方式将它完全加载到 RAM 中吗? Here 是我的统计数据。从查询中排除 bnode 并使用模型 api 获取数据会更有用吗?谢谢抢,丹尼尔
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多