Wikidata SPARQL查询超时求助:添加schema:about后查询超时
问题描述
在Wikidata上执行SPARQL查询,目标是获取所有人口大于指定数值的城市数据。原本的查询可正常运行,但添加schema:about语句以获取对应英文维基百科文章链接后,查询开始超时。询问是否存在操作错误,或是有优化该查询的方法。
可正常运行的原始查询
SELECT DISTINCT ?city ?cityLabel ?population ?country ?countryLabel ?loc WHERE { ?city wdt:P31/wdt:P279* wd:Q515 . ?city wdt:P1082 ?population . ?city wdt:P17 ?country . ?city wdt:P625 ?loc . FILTER (?population >= 1000000) . SERVICE wikibase:label { bd:serviceParam wikibase:language "en" . } } ORDER BY DESC(?population)
添加文章查询后超时的版本
SELECT DISTINCT ?city ?cityLabel ?population ?country ?countryLabel ?loc ?article WHERE { ?city wdt:P31/wdt:P279* wd:Q515 . ?city wdt:P1082 ?population . ?city wdt:P17 ?country . ?city wdt:P625 ?loc . FILTER (?population >= 1000000) . ?article schema:about ?city . ?article schema:isPartOf <https://en.wikipedia.org/>. SERVICE wikibase:label { bd:serviceParam wikibase:language "en" . } } ORDER BY DESC(?population)
优化方案与问题分析
问题原因
你的操作没有错误,查询超时是因为schema:about关联的是维基百科的结构化数据,这类数据的三元组数量极大。原始查询先过滤出符合条件的城市后直接返回,而添加schema:about后,查询引擎会先将所有符合条件的城市与所有schema:about三元组做笛卡尔积关联,再进行过滤和排序,导致计算负载急剧升高,最终超时。
优化方法
方法1:使用子查询缩小关联范围
先通过子查询筛选出所有符合条件的城市数据,再关联维基百科文章链接,这样能大幅减少后续关联的数据量:
SELECT ?city ?cityLabel ?population ?country ?countryLabel ?loc ?article WHERE { # 子查询先筛选核心城市数据,减少后续关联的数据量 { SELECT DISTINCT ?city ?cityLabel ?population ?country ?countryLabel ?loc WHERE { ?city wdt:P31/wdt:P279* wd:Q515 . ?city wdt:P1082 ?population . ?city wdt:P17 ?country . ?city wdt:P625 ?loc . FILTER (?population >= 1000000) . SERVICE wikibase:label { bd:serviceParam wikibase:language "en" . } } } # 仅针对筛选后的城市关联维基百科文章 ?article schema:about ?city . ?article schema:isPartOf <https://en.wikipedia.org/>. } ORDER BY DESC(?population)
方法2:直接构造维基百科链接(更高效)
如果不需要严格匹配维基百科的结构化数据链接,可以通过城市标签直接构造英文维基百科的文章URL,完全避免关联schema数据,速度最快:
SELECT DISTINCT ?city ?cityLabel ?population ?country ?countryLabel ?loc ?article WHERE { ?city wdt:P31/wdt:P279* wd:Q515 . ?city wdt:P1082 ?population . ?city wdt:P17 ?country . ?city wdt:P625 ?loc . FILTER (?population >= 1000000) . SERVICE wikibase:label { bd:serviceParam wikibase:language "en" . } # 直接构造维基百科文章链接 BIND(CONCAT("https://en.wikipedia.org/wiki/", REPLACE(?cityLabel, " ", "_")) AS ?article) } ORDER BY DESC(?population)
额外优化点
- 去掉不必要的
DISTINCT:如果每个城市仅对应一篇英文维基百科文章,关联后不会产生重复结果,可以移除DISTINCT进一步降低查询负载。
内容的提问来源于stack exchange,提问作者Ankit Agarwal
相关产品推荐
相关产品推荐

