0

我正在尝试将 XQuery/XPath 与mondial 数据库的 XML 版本一起使用,以查找彼此相距最远的两个城市,仅考虑人口超过 500,000 的城市。为了计算距离,我假设一个墨卡托投影

这是我的代码:

let $db := doc("mondial.xml")

(: Cities with 500,000+ population :)
let $cities := (for $city in $db/mondial/country//city
(: Compare using latest population data :)
where $city/population[@year = max($city/population/@year)] > 500000
return $city)

(: City pairs and the distances between them (not
not square-rooted as all we care about is order) :)
let $distancesSquared := (for $city1 in $cities
for $city2 in $cities
    where $city1 != $city2
    return <distancesquared city1="{ data($city1/name) }" city2="{ data($city2/name) }">{ (
        let $diffLong := number($city1/longitude) - number($city2/longitude)
        let $diffLat := number($city1/latitude) - number($city2/latitude)
        return $diffLong * $diffLong + $diffLat * $diffLat
    ) }</distancesquared>)

let $max := max($distancesSquared)

return $distancesSquared[data(.) = $max]

但由于某种原因,我在这一行遇到了分段错误:

let $max := max($distancesSquared)

xqilla用来运行这样的查询:

xqilla -o query.xml query.xq

任何想法我的代码可能有什么问题?

4

1 回答 1

3

这是一个非常糟糕的查询,因为中间数据量随输入数据量呈二次方变化。

因为变量 $distancesSquared 被引用了两次,它几乎肯定会在内存中实现,而且很可能是巨大的。

首先检查数据量较小时是否仍会出现故障。如果即使是小型数据集也会发生这种情况,那么您的代码没有问题,这是 XQuilla 中的一个错误。

如果它只发生在大型数据集上,那么您可能超出了某种系统限制(可能是内存);检查是否有可以调整的配置参数。

更好:找到改进的算法。

第一步,尝试一种在时间上仍然是二次方但在内存中不再是二次方的算法:具体来说,对于每个城市,找到最远的城市;在表格中建立一个列表

<city name="London" furthest="Christchurch" distance="8000"/>

ETC; 然后在这个城市对列表中找到最大值。

更聪明的是,有一些方法可以在不检查所有城市对的情况下解决这个问题。恐怕我研究这种算法已经有一段时间了,所以我不记得细节了。但总体思路是将每个城市分配到一个区域,计算出每对区域中点之间的极端距离,然后在找到距离给定城市最远的城市时,只处理距离足够远的区域。

于 2017-04-24T17:14:33.687 回答