繁体   English   中英

优化mysql查询以使用空间索引选择多边形中的所有点

[英]Optimizing mysql query to select all points with in polygon using spatial indexes

首先,我承认我的空间功能经验非常少。 我在MySQL中有一个包含20个字段的表和23549187个包含地理数据的记录。 其中一个字段是“点”,它是点数据类型并且在其上具有空间索引。 我有一个查询,选择多边形内的所有点,如下所示,

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输出:

+----+-------------+------------+------+---------------+------+---------+------+----------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows     | Extra       |
+----+-------------+------------+------+---------------+------+---------+------+----------+-------------+
|  1 | SIMPLE      | table_name | ALL  | NULL          | NULL | NULL    | NULL | 23549187 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+----------+-------------+

用较小的多边形解释sql输出以进行查询,

+----+-------------+------------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table      | type  | possible_keys | key      | key_len | ref  | rows | Extra       |
+----+-------------+------------+-------+---------------+----------+---------+------+------+-------------+
|  1 | SIMPLE      | table_name | range | sp_index      | sp_index | 34      | NULL |    1 | Using where |
+----+-------------+------------+-------+---------------+----------+---------+------+------+-------------+

看起来最大的多边形不使用索引。

MySQL使用R-Trees来索引空间数据。 B-Tree索引一样 ,这些索引最适合针对总数的一小部分的查询。 随着边界多边形变大,可能匹配的数量增加,并且在某些时候,优化器决定切换到全表扫描更有效。 这似乎是这里的情景,我看到三个选项:

首先,尝试在查询中添加LIMIT 通常,如果优化器在完整表扫描中得出的I / O搜索次数较少,则MySQL会忽略该索引。 但是,至少使用B-Tree索引,MySQL将使该逻辑短路并且在LIMIT存在时始终执行B-Tree潜水。 我假设R-Tree有类似的短路。

其次,与第一个类似,尝试强制MySQL使用索引 这指示MySQL表扫描比优化器决定的更昂贵。 理解优化器只有启发式,并且不知道“昂贵”的东西是如何超出其内部统计数据的结论。 我们人类有直觉,有时 - 有时 - 知道更好。

select * force index (`sp_index`) 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`)

最后,如果那些不起作用,那么你需要做的是将边界多边形分解成更小的多边形。 例如,如果您的边界多边形是每边500公里的正方形,则将其分成每边250平方公里的4个方格,或每边125平方公里,等等。然后UNION所有这些组合在一起。 索引将用于每个索引,累积结果可能更快。 (注意:这是重要的UNION在一起:MySQL不能在空间查询应用多个范围扫描)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM