【发布时间】:2018-11-07 01:10:13
【问题描述】:
首先,我承认我在空间函数方面的经验非常少。我在 MySQL 中有一个表,其中包含 20 个字段和 23549187 条包含地理数据的记录。其中一个字段是“point”,它是点数据类型,并在其上具有空间索引。我有一个查询选择多边形内的所有点,如下所示,
select * from `table_name` where ST_CONTAINS(ST_GEOMFROMTEXT('POLYGON((151.186 -23.497,151.207 -23.505,151.178 -23.496,151.174 -23.49800000000001,151.176 -23.496,151.179 -23.49500000000002,151.186 -23.497))'), `point`)
这很好用,因为多边形很小。但是,如果多边形变得很大,执行时间会变得非常慢,并且迄今为止最慢的查询运行了 15 分钟。添加索引确实有助于将其缩短到 15 分钟,否则将需要将近一个小时。我可以在这里做些什么来进一步改进。 此查询将由作为守护程序运行的 PHP 脚本运行,我担心这种缓慢的查询是否会导致 MySQL 服务器停机。
欢迎提出任何使其变得更好的建议。谢谢。
编辑:
show create table;
CREATE TABLE `table_name` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`lat` float(12,6) DEFAULT NULL,
`long` float(12,6) DEFAULT NULL,
`point` point NOT NULL,
PRIMARY KEY (`id`),
KEY `lat` (`lat`,`long`),
SPATIAL KEY `sp_index` (`point`)
) ENGINE=MyISAM AUTO_INCREMENT=47222773 DEFAULT CHARSET=utf8mb4
还有几个字段我不应该在这里透露,但是过滤器赢了
解释慢查询的 sql 输出:
+----+-------------+------------+------+------- --------+------+---------+------+----------+------ --------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+------------+------+---------- -----+------+---------+------+----------+--------- ----+ | 1 |简单 |表名 |全部 |空 |空 |空 |空 | 23549187 |使用位置 | +----+-------------+------------+------+---------- -----+------+---------+------+----------+--------- ----+
用较小的多边形解释查询的 sql 输出,
+----+-------------+------------+-------+------ ------+---------+---------+------+------+----- --------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+------------+-------+--------- ------+----------+---------+------+------+-------- -----+ | 1 |简单 |表名 |范围 | sp_index | sp_index | 34 |空 | 1 |使用位置 | +----+-------------+------------+-------+--------- ------+----------+---------+------+------+-------- -----+
看起来最大的多边形没有使用索引。
【问题讨论】:
-
将其移至dba.stackexchange.com 或gis.stackexchange.com 可能会更好
-
对于大规模,你的意思是大尺寸(大边界框,就像覆盖整个地球),和/或数千个点的复杂形状,和/或包含很多/所有的积分? MySQL 似乎已经决定使用后者,您能否验证是这种情况(例如,您在结果集中获得了 2300 万个点中的很大一部分)?
-
慢的一个或两个?更重要的问题是它里面有多少点,特别是多边形的边界框中有多少点(如果你在多边形周围做一个正方形,里面会有多少点 - 这是索引的部分提供)。虽然可能没有一种简单的方法可以加快查询速度,但对多边形形状有一个大致的了解会有所帮助(请参阅主教的回答):如果您的多边形例如描述一个圆,你可以通过使用一个内部正方形(便于索引)来消除 60% 的比较,然后将剩余的 4 个圆部分合并到它。
-
这些数字很大。为 6k 多边形检查可能有 500k 点(位于多边形附近)将花费大量时间。我不确定您是否可以从一般角度优化您的查询。您可能需要结合其他有关您的情况的因素。例如:如果您的多边形是佛罗里达州的 6k 多边形,并且您想知道其中有哪些客户,您可以存储/预先计算某人住在迈阿密,然后您只需要检查迈阿密是否在佛罗里达州即可获得一次比较中 30% 的结果。
-
或者也许你可以简化你的多边形,因为你不需要 4k 点来详细描述基韦斯特的海岸线,因为没有合理的期望有人真的住在墨西哥的高尔夫球场,所以10 点而不是 4k 可能就足够了。您的问题可能会有这样的聚类或推理,艰巨的任务可能是找到一个。您需要添加有关您的问题的详细信息,和/或您可能想在gis.stackexchange.com 上描述您的问题,也许他们有一个想法。
标签: php mysql sql spatial-query spatial-index