最近点上的MySQL空间连接

最近点上的MySQL空间连接,mysql,sql,spatial,Mysql,Sql,Spatial,我环顾了一下四周,发现不少人都在寻找一个点到设定点的距离表,但我好奇的是,如何在两个点之间的最小距离上有效地连接两个表。在我的例子中,考虑表节点< /代码>和质心< /代码> ./p> 创建表节点( 节点id VARCHAR(255), pt点 ); 创建表格质心( 质心id中间无符号, 温度浮动, pt点 ); 我有大约300k个节点和15k个质心,我想得到每个节点最近的质心,这样我可以为每个节点分配一个温度。到目前为止,我已经在两个表的pt上创建了空间索引,并尝试运行以下查询: 选择 no

我环顾了一下四周,发现不少人都在寻找一个点到设定点的距离表,但我好奇的是,如何在两个点之间的最小距离上有效地连接两个表。在我的例子中,考虑表<代码>节点< /代码>和<代码>质心< /代码> ./p>
创建表节点(
节点id VARCHAR(255),
pt点
);
创建表格质心(
质心id中间无符号,
温度浮动,
pt点
);
我有大约300k个节点和15k个质心,我想得到每个节点最近的质心,这样我可以为每个节点分配一个温度。到目前为止,我已经在两个表的
pt
上创建了空间索引,并尝试运行以下查询:

选择
nodes.node_id,
最小(ST_距离(nodes.pt,centroids.pt))
从节点
内连接质心

在ST_距离(nodes.pt,centroids.pt)上,有许多方法可以解决这个最小n个组的问题

一种方法使用自左连接反模式(这允许绑定):

最后:如果您只需要最近质心的
温度
,那么简单的子查询应该是一个不错的选择:

select 
    n.node_id,
    (
        select c1.temperature
        from centroids c1
        order by st_distance(n.pt, c1.pt) 
        limit 1
    ) temperature 
from nodes n

我认为一个好的方法是将数据划分为单元(数值上不是db划分)。我不知道空间索引在这里的应用情况如何,但高级逻辑是将每个节点和质心点放入正方形区域,并在同一个正方形中的所有节点质心之间找到匹配,然后确保在8个相邻的正方形中没有更接近的匹配(例如,在原始正方形中使用相同的节点)。然后可以使用最接近的匹配来计算和保存温度。所有后续查询都应忽略设置了温度的节点


仍然会有质心不在相同或8个相邻正方形内的节点,然后您可以展开搜索,可能使用宽度和高度加倍的正方形。我可以看到它仅在点的x和y坐标上使用普通索引。我不知道空间索引如何进一步改善这一点。

感谢您的工作查询。它们的运行限制很低,但MySQL似乎仍然没有使用任何索引。100个节点需要2.14秒,1000个节点需要21.33秒,10000个节点需要212.94秒。因此,一个完整的网络(更新后为500k节点)需要大约3小时,这肯定是可以管理的,但进一步优化它会很好。有没有关于如何实际利用mysql空间索引的想法,或者这不是它们的设计目的?你提到的cells提出了一个想法。我知道MySQL空间索引可以快速查找特定多边形内或周围的项目。是否可以将质心转换为多边形的细分,然后只搜索每个多边形包含的节点?这会比试图计算距离快得多吗?听起来真的很酷,你知道多边形中的所有节点都将最接近其中一个顶点质心。因此,现在的问题变成了进行细分。三角形怎么样。记住,“外部”(网格的负多边形)也是那些不在内部的节点的多边形。这实际上不起作用。因为在“\/”中,右三角形中非常靠近左侧的点可能比右三角形中的任何点更靠近左三角形的左上点。也许还是用正方形比较好。这些呢?我可以拉所有的质心,用python计算它们的Voronoi多边形,然后把它们推回去。这些多边形的空间索引应该很快。是的,Voronoi多边形的计算和使用这些区域将温度与节点配对的速度惊人地快。我可以在几秒钟内完成我想在整个网络上加入的任务。我会接受你的回答,感谢你在这里的帮助,并在我自己对问题的回答中解释我所做的事情。
select 
    n.node_id,
    n.node_id,
    c.centroid_id,
    st_distance(n.pt, c.pt) dist,
    c.temperature
from nodes n
inner join centroids c
    on c.centroid_id = (
        select c1.centroid_id
        from centroids c1
        order by st_distance(n.pt, c1.pt) 
        limit 1
    )
select 
    n.node_id,
    (
        select c1.temperature
        from centroids c1
        order by st_distance(n.pt, c1.pt) 
        limit 1
    ) temperature 
from nodes n