我已经找到了各种类似于这个问题的解决方案的问题,但到目前为止还没有任何关于钱的问题。非常感谢任何帮助。
我有一个mysql(v.5.6.10)数据库,其中包含一个名为POSTS的表,可以在地图上存储数百万行纬度/经度。每个点被分类为几种不同类型中的一种。每行的结构为id, type, coords
:
id
unsigned bigint
+主键。对于插入的每个新行,这会自动递增。type
unsigned tinyint
用于编码兴趣点的类型。 coords
一个mysql地理空间POINT
数据类型,表示兴趣点的纬度/经度。'coords'上有一个SPATIAL索引。
我需要找到一种有效的方法来查询表格并返回特定纬度/经度位置半径(“ R ”)内最近插入的点的X(“的位置“)。数据库非常动态,因此请假设每次查询表时数据都完全不同。
如果X是无限的,问题就是微不足道的。我只需要执行类似的查询:
SELECT id, type, AsText(coords) FROM POSTS WHERE MBRContains(GeomFromText(BoundingBox, Position))
其中'BoundingBox'是一个mysql POLYGON数据类型,它完美地包围了位置半径为R的圆。当然,使用边界框并不是一个完美的解决方案,但这对我正在尝试解决的特定问题并不重要。我可以使用“ORDER BY ID DESC”来排序结果,以便首先检索和处理最近插入的点。
如果X小于无穷大,那么我只需将上述内容修改为:
SELECT id, type, AsText(coords) FROM POSTS WHERE MBRContains(GeomFromText(BoundingBox, Position)) ORDER BY id DESC LIMIT X
我想解决的问题是,当该区域中的点被大量聚集时(例如,在地图搜索区域内的城市内),如何从地图上的给定区域获得一组良好的代表性结果集? 。例如:
在上面的示例中,我站在X并在黑框边界框中搜索最近插入的5个黑色点。如果这些点全部插入到右下角的聚类中(假设聚类是伦敦),那么我的结果集将不包括搜索区域右上角附近的黑点。这对我的应用程序来说是一个问题,因为我不希望给用户的印象是在点聚集的任何区域之外没有兴趣点。
我考虑了一些潜在的解决方案,但是当行数很大(数百万)时,我找不到一个有效的解决方案。到目前为止我尝试过的方法包括:
将搜索区域划分为S个正方形(即,将其转换为网格)并在每个正方形内搜索最多x / S点 - 即,对网格中的每个正方形执行单独的mysql查询。这适用于少量行,但当行数很大时变得效率低,因为您需要将区域划分为大量方块以使方法有效工作。如果只有少量方块,则无法保证每个方块不包含人口密集的群集。大量的正方形意味着大量的mysql搜索会导致事情发生。
向表中的每一行添加一列,用于存储每个点到最近邻居的距离。当将点插入表中时,计算给定点的最近邻距离。通过这种结构,我可以按最近邻距离列对搜索结果进行排序,以便最后返回簇中的任何点。此解决方案仅在我搜索搜索区域内的所有点时有效。例如,请考虑上图所示的情况。如果我想找到5个最近插入的绿色类型的点,则为每个点记录的最近邻居距离将不正确。即使使用像KD树这样的高效算法,重新计算每个查询的这些距离也会非常昂贵。
事实上,我看不到任何需要在表行中预处理数据的方法(或者换句话说,'触摸'相关搜索区域数据集中的每个点)在行数时是可行的变大了。我考虑过k-means / DBSCAN等算法,但鉴于上面解释的用例,我找不到任何能够充分发挥效率的算法。
任何珍珠?我的直觉告诉我这可以解决但到目前为止我很难过。
答案 0 :(得分:1)
在这种情况下的后处理似乎更有效。获取给定类型的最后X个点。查找是否存在某些聚类,例如:相对于您的视点距离,太多的点太靠近在一起。删除最旧的(或非常接近的 - 可能是您的数据引用相同的POI)。多少 - 取决于你。获取下一个X点并查看其中是否有一些不在群集中,或者您可以根据远程性和近期性计算每个点的值,并根据该值计算丢弃点。