iPhone硬计算和缓存
我有问题。我的数据库中有500k记录。每个记录存储纬度、经度、动物种类、观察日期。我必须在mapkit视图上方绘制网格(15x10),显示该网格单元中物种的浓度。每个单元为32x32盒 如果在运行时进行计算,则速度非常慢。 有人知道如何将其缓存在内存或数据库中吗 数据结构: 观察:iPhone硬计算和缓存,iphone,database,algorithm,Iphone,Database,Algorithm,我有问题。我的数据库中有500k记录。每个记录存储纬度、经度、动物种类、观察日期。我必须在mapkit视图上方绘制网格(15x10),显示该网格单元中物种的浓度。每个单元为32x32盒 如果在运行时进行计算,则速度非常慢。 有人知道如何将其缓存在内存或数据库中吗 数据结构: 观察: 纬度 经度 日期 物种 其他一些不重要的数据 屏幕示例: 每一个红盒数量都显示了该地区的物种数量 我现在使用的代码: 数据->从数据库中选择,都是地图区域的观测 for (int row = 0; row &l
- 纬度
- 经度
- 日期
- 物种
- 其他一些不重要的数据
for (int row = 0; row < rows; row++)
{
for (int column = 0; column < columns; column++)
{
speciesPerBox=0;
minG=boxes[row][column].longitude;
if (column!=columns-1) {
maxG=boxes[row][column+1].longitude;
} else {
maxG=buttomRight.longitude;
}
maxL=boxes[row][column].latitude;
if (row!=rows-1) {
minL=boxes[row+1][column].latitude;
} else {
minL=buttomRight.latitude;
}
for (int i=0; i<sightingCount; i++) {
l=data[i].latitude;
g=data[i].longitude;
if (l>=minL&&l<maxL&&g>=minG&&g<maxG) {
for (int j=0; j<speciesPerBox; j++) {
if (speciesCountArray[j]==data[i].specie) {
hasSpecie=YES;
}
}
if (hasSpecie==NO) {
speciesCountArray[speciesPerBox]=data[i].specie;
speciesPerBox++;
}
hasSpecie=NO;
}
}
}
mapData[row][column].count = speciesPerBox;
}
}
for(int row=0;row 对于(int i=0;i=minL&&l=minG&&g由于数据是静态的,因此可以预先计算每个网格的每个物种,并将其存储在数据库中,而不是所有位置坐标
因为您有15 x 10=150个单元格,所以数据库中最终会有150个*[num of species]记录,这应该是一个小得多的数字
另外,请确保在正确的列上有索引。否则,您的查询将不得不反复扫描每条记录。循环(int i=0;i=minL&&l=minG&&g=90)maxL-=90;//检查您的刻度,我假设为90°
}
也许这也适用于经度循环,但经度可能不会均匀分布(即“incG”在每个步骤中都不同)
请注意,空间优化将产生巨大的差异,,循环优化只是很小(但仍然值得)不同之处。对于500k记录,这听起来像是核心数据的工作。最好是在桌面上更新核心数据。如果数据没有实时更新,你应该在较重的硬件上处理数据,只需使用iPhone来显示。这将大大简化应用程序,因为你只需要存储每个地图单元格的值
即使你真的想在iPhone上处理它,你也应该让应用程序处理数据一次并保存结果。似乎没有理由让应用程序每次想不显示单元格时都重新计算每个地图单元格的物种值
我建议在核心数据中创建一个实体来表示观测值。然后创建另一个实体来表示地理广场。在广场和广场内的观测值之间设置一个关系。然后在广场实体中创建物种的计算值。如果有,您只需重新计算物种值观察结果的百分比发生了变化
这就是创建对象图的目的。即使数据不断更新,核心数据也只会执行在任何给定时间发生变化的少量观测对象所需的计算,并且会以高度优化的方式进行
Edit01:
从一个完全不同的角度处理问题。在核心数据中
(1) 创建观察记录的对象图,使每个观察对象与地理上最接近的其他观察对象具有相互关系。这将创建一个看起来像平面不规则网的对象图
(2) 为observationRecords类创建方法,该类方法(a)确定记录是否位于任意地理广场的边界内(b)询问其每个相关记录是否也位于广场内(c)返回其自身的物种计数和所有相关记录的计数
(三)将地图划分为一些合理的小正方形,例如弧正方形的1秒。在该正方形内选择一条链接记录并将其添加到列表中。从所有记录中选择一定百分比,如每100条或每1000条中选择1条,以便将列表从500k减少到创建一个子列表,该子列表可由暴力谓词快速搜索。让我们调用列表中的记录将显示gridflags
(4) 当用户放大时,使用暴力查找地理网格中的所有gridflag记录。然后要求每个gridflag记录向其每个链接记录发送消息,以查看(a)它们是否在网格内,(b)它们的物种数是多少,以及(c)它们也在网格内的链接记录的计数是多少。(使用标志确保每个记录每次搜索只查询一次,以防止失控递归。)
这样,您只需在每个任意大小的网格单元内找到一条记录,该记录将为您找到所有其他记录。您不必每次单步查看每条记录以查看哪个记录进入哪个单元,而只需处理每个单元和相邻单元中的记录。放大时,记录的数量您实际查询的rds会收缩,而不是保持不变。如果网格单元格只有少量记录,则您只需查询少量记录
这将需要一些努力和时间来设置,但一旦你这样做了,它将是相当有效的,尤其是当放大的方式。对于顶级,只需有一个预处理的静态地图
希望我解释得足够好。这很难用语言表达。如果用户缩放地图,我需要重新计算所有数据,用户可以通过触摸移动地图,我也需要重新计算。您有多少缩放级别?预先计算最高级别的缩放(因为它们的计算成本最高).如果您允许用户任意缩放,则无法真正减少所需的计算量。您
maxL=boxes[0][0].latitude;
minL=boxes[rows-1][0].latitude;
incL=maxL-minL;
for( int row = 0; row < rows; row++ )
{
for( int column = 0; column < columns; column++ )
{
speciesPerBox=0;
minG=boxes[row][column].longitude;
if (column!=columns-1) {
maxG=boxes[row][column+1].longitude;
} else {
maxG=buttomRight.longitude;
}
...
...
}
...
minL = maxL; // left edge = right edge of previous step
maxL += incL; // increment right edge
if( maxL >= 90 ) maxL -= 90; // check your scale, i assume 90°
}