为啥这个 SPARQL 查询超时以及如何优化这个查询?
Posted
技术标签:
【中文标题】为啥这个 SPARQL 查询超时以及如何优化这个查询?【英文标题】:Why this SPARQL query times out and how to optimize this query?为什么这个 SPARQL 查询超时以及如何优化这个查询? 【发布时间】:2020-07-29 13:03:24 【问题描述】:我有这个通过 Wikidata 端点运行的 SPARQL 查询
SELECT ?bLabel ?b ?hLabel ?a ?cLabel
WHERE
wd:Q11462 ?a ?b.
wd:Q11095 ?a ?b.
?c ?a ?b.
?h wikibase:directClaim ?a .
SERVICE wikibase:label bd:serviceParam wikibase:language "en"
基本上,我正在寻找由 wd:Q11462 和 wd:Q11095 共享的关系,并查看还有什么共享该关系。它达到了 60 秒的时间限制。
但是,如果我分两部分运行多个查询:
首先,获取共享关系
SELECT ?bLabel ?b ?hLabel ?a
WHERE
wd:Q11462 ?a ?b.
wd:Q11095 ?a ?b.
?h wikibase:directClaim ?a .
SERVICE wikibase:label bd:serviceParam wikibase:language "en"
然后,对于每个获得的关系,运行一个查询以查找与他们共享的其他内容。
"""
SELECT ?cLabel
WHERE
?c wdt:P131 wd:Q3586.
SERVICE wikibase:label bd:serviceParam wikibase:language "en"
"""
整个查询只运行 2.5 秒。
由于限制,我希望只用一个查询就能达到同样的速度。我该怎么办?
【问题讨论】:
【参考方案1】:这是一种使用子查询的方法。需要六秒钟:
SELECT ?cLabel
WITH
SELECT ?bLabel ?b ?hLabel ?a
WHERE
wd:Q11462 ?a ?b.
wd:Q11095 ?a ?b.
?h wikibase:directClaim ?a .
as %results
WHERE
INCLUDE %results.
?c wdt:P131 wd:Q3586.
SERVICE wikibase:label bd:serviceParam wikibase:language "en"
考虑到您观察到的明显差异以及它们在概念上与您连续运行多个查询的方法的接近程度,子查询是自然的扩展。一个更通用的技巧通常会有所帮助,即用手动查询标签来替换标签服务。
在切换到一些具有较少(常用)语句的项目后,我说服了查询服务explain itself。我不能完全声称理解该输出,但据我所知是标签服务将其丢弃(底部表格中的第 5 行):
9 com.bigdata.bop.BOp.bopId
CONTROLLER com.bigdata.bop.BOp.evaluationContext
false com.bigdata.bop.PipelineOp.pipelined
true com.bigdata.bop.PipelineOp.sharedState
ServiceNode com.bigdata.bop.controller.ServiceCallJoin.serviceNode
wdq com.bigdata.bop.controller.ServiceCallJoin.namespace
1596209250127 com.bigdata.bop.controller.ServiceCallJoin.timestamp
[b, h, c] com.bigdata.bop.join.HashJoinAnnotations.joinVars
null com.bigdata.bop.join.JoinAnnotations.constraints
此时似乎它试图为 20000 多个项目填充标签。除了将其排除在第一个查询之外,SPARQL 还提供了添加关于理想操作序列的提示的能力,这可能在这里很有用。
【讨论】:
我认为应该是?c ?a ?b
,但您的分析似乎是正确的。当我删除该服务时,它显着提高了速度。谢谢。以上是关于为啥这个 SPARQL 查询超时以及如何优化这个查询?的主要内容,如果未能解决你的问题,请参考以下文章