在 SPARQL 查询中按 birthYear 和 deathYear 标准过滤人员更具性能
Make filtering people by birthYear and deathYear criteria more performative in SPARQL query
我想找到在质数年出生和去世的科学家的实例。基于先前在 this URL 上的讨论,我设计了以下查询,该查询很笨拙且会超时:
SELECT ?birthYear ?deathYear ?scientist ?scientistLabel
WHERE
{
{
select ?value1
{
?number wdt:P31 wd:Q49008.
?number wdt:P1181 ?value1
filter(?value1 < year(now()))
}
}
{
select ?value2
{
?number wdt:P31 wd:Q49008.
?number wdt:P1181 ?value2
filter(?value2 < ?value1)
}
}
?scientist wdt:P106 wd:Q901.
?scientist wdt:P570 ?deathDate.
?scientist wdt:P569 ?birthDate
BIND(year(?deathDate) as ?deathYear)
BIND(year(?birthDate) as ?birthYear)
filter(?deathYear = ?value1)
filter(?birthYear = ?value2)
SERVICE wikibase:label { bd:serviceParam wikibase:language " [AUTO_LANGUAGE],en". }
}
order by asc(?deathYear) asc(?scientistLabel)
limit 100
我是 SPARQL 新手,但据我所知,这将取一对质数,然后查看职业为 'scientist' 的人是否在与第一个对应的年份死亡,那么如果那个人出生在对应于2号的那一年。
有没有办法提高这个查询的性能?
您的查询有 2 个问题:
- 不能以这种方式将值传递到子查询(参见 Bottom Up Semantics)。
wdt:P1181
的值为 xsd:decimal
,而 year()
returns xsd:integer
。一个人被迫使用 FILTER(?birthYear = ?value)
,它的性能和可优化性都比简单的连接差。看来 Blazegraph 必须过早地具体化解决方案。
因此,您的查询应该是:
SELECT DISTINCT ?scientist ?scientistLabel ?birthYear ?deathYear {
{
SELECT (xsd:integer(?value1) as ?birthYear) {
?number wdt:P31 wd:Q49008.
?number wdt:P1181 ?value1
FILTER(?value1 < year(now()))
}
}
{
SELECT (xsd:integer(?value2) AS ?deathYear) {
?number wdt:P31 wd:Q49008.
?number wdt:P1181 ?value2
FILTER(?value2 < year(now()))
}
}
?scientist wdt:P106 wd:Q901.
?scientist wdt:P570 ?deathDate.
?scientist wdt:P569 ?birthDate.
FILTER(isLiteral(?birthDate) && isLiteral(?deathDate))
BIND(year(?deathDate) AS ?deathYear)
BIND(year(?birthDate) AS ?birthYear)
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
} ORDER BY ASC(?birthDate) ASC(?deathDate)
我还添加了 FILTER(isLiteral(?birthDate))
,因为 wdt:P1181
的值可能是 unknown values(即 RDF 空白节点),在这种情况下 BIND (year(?birthDate) AS ?birthYear)
投影变量始终未绑定并匹配连接中的所有内容。
您可以使用 Blazegraph 特定技巧进一步加快查询速度:
SELECT DISTINCT ?scientist ?scientistLabel ?birthYear ?deathYear
WITH {
SELECT (xsd:integer(?value) AS ?year) {
[] wdt:P31 wd:Q49008 ; wdt:P1181 ?value.
hint:Prior hint:rangeSafe true.
FILTER(?value <= year(now()))
}
} AS %primes {
# hint:Query hint:maxParallel 50 .
# hint:Query hint:chunkSize 250 .
{ SELECT (?year AS ?birthYear) { include %primes } }
{ SELECT (?year AS ?deathYear) { include %primes } }
?scientist wdt:P106 wd:Q901.
?scientist wdt:P570 ?deathDate.
?scientist wdt:P569 ?birthDate.
FILTER (isLiteral(?deathDate) && isLiteral(?birthDate))
BIND (year(?birthDate) AS ?birthYear)
BIND (year(?deathDate) AS ?deathYear)
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} ORDER BY ASC(?birthYear) ASC (?deathYear)
我想找到在质数年出生和去世的科学家的实例。基于先前在 this URL 上的讨论,我设计了以下查询,该查询很笨拙且会超时:
SELECT ?birthYear ?deathYear ?scientist ?scientistLabel
WHERE
{
{
select ?value1
{
?number wdt:P31 wd:Q49008.
?number wdt:P1181 ?value1
filter(?value1 < year(now()))
}
}
{
select ?value2
{
?number wdt:P31 wd:Q49008.
?number wdt:P1181 ?value2
filter(?value2 < ?value1)
}
}
?scientist wdt:P106 wd:Q901.
?scientist wdt:P570 ?deathDate.
?scientist wdt:P569 ?birthDate
BIND(year(?deathDate) as ?deathYear)
BIND(year(?birthDate) as ?birthYear)
filter(?deathYear = ?value1)
filter(?birthYear = ?value2)
SERVICE wikibase:label { bd:serviceParam wikibase:language " [AUTO_LANGUAGE],en". }
}
order by asc(?deathYear) asc(?scientistLabel)
limit 100
我是 SPARQL 新手,但据我所知,这将取一对质数,然后查看职业为 'scientist' 的人是否在与第一个对应的年份死亡,那么如果那个人出生在对应于2号的那一年。 有没有办法提高这个查询的性能?
您的查询有 2 个问题:
- 不能以这种方式将值传递到子查询(参见 Bottom Up Semantics)。
wdt:P1181
的值为xsd:decimal
,而year()
returnsxsd:integer
。一个人被迫使用FILTER(?birthYear = ?value)
,它的性能和可优化性都比简单的连接差。看来 Blazegraph 必须过早地具体化解决方案。
因此,您的查询应该是:
SELECT DISTINCT ?scientist ?scientistLabel ?birthYear ?deathYear {
{
SELECT (xsd:integer(?value1) as ?birthYear) {
?number wdt:P31 wd:Q49008.
?number wdt:P1181 ?value1
FILTER(?value1 < year(now()))
}
}
{
SELECT (xsd:integer(?value2) AS ?deathYear) {
?number wdt:P31 wd:Q49008.
?number wdt:P1181 ?value2
FILTER(?value2 < year(now()))
}
}
?scientist wdt:P106 wd:Q901.
?scientist wdt:P570 ?deathDate.
?scientist wdt:P569 ?birthDate.
FILTER(isLiteral(?birthDate) && isLiteral(?deathDate))
BIND(year(?deathDate) AS ?deathYear)
BIND(year(?birthDate) AS ?birthYear)
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
} ORDER BY ASC(?birthDate) ASC(?deathDate)
我还添加了 FILTER(isLiteral(?birthDate))
,因为 wdt:P1181
的值可能是 unknown values(即 RDF 空白节点),在这种情况下 BIND (year(?birthDate) AS ?birthYear)
投影变量始终未绑定并匹配连接中的所有内容。
您可以使用 Blazegraph 特定技巧进一步加快查询速度:
SELECT DISTINCT ?scientist ?scientistLabel ?birthYear ?deathYear
WITH {
SELECT (xsd:integer(?value) AS ?year) {
[] wdt:P31 wd:Q49008 ; wdt:P1181 ?value.
hint:Prior hint:rangeSafe true.
FILTER(?value <= year(now()))
}
} AS %primes {
# hint:Query hint:maxParallel 50 .
# hint:Query hint:chunkSize 250 .
{ SELECT (?year AS ?birthYear) { include %primes } }
{ SELECT (?year AS ?deathYear) { include %primes } }
?scientist wdt:P106 wd:Q901.
?scientist wdt:P570 ?deathDate.
?scientist wdt:P569 ?birthDate.
FILTER (isLiteral(?deathDate) && isLiteral(?birthDate))
BIND (year(?birthDate) AS ?birthYear)
BIND (year(?deathDate) AS ?deathYear)
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} ORDER BY ASC(?birthYear) ASC (?deathYear)