我有两个表:一个有点,另一个有多边形。
CREATE TABLE `points` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`point` point NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
CREATE TABLE `ranges` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`poly` polygon NOT NULL,
PRIMARY KEY (`id`),
SPATIAL KEY `poly` (`poly`)
) ENGINE=MyISAM;
我希望将范围加入到多边形内的点上。查询看起来很简单:
SELECT *
FROM points
LEFT JOIN ranges
ON MBRCONTAINS(poly, point)
WHERE points.id = 2;
此查询工作正常并使用索引,解释的一部分:
表| 类型| possible_keys | 关键| key_len 范围| 范围| 聚| 聚| 34
但是,当我尝试从表中连接几行时points
:
SELECT *
FROM points
LEFT JOIN ranges
ON MBRCONTAINS(poly, point)
WHERE points.id IN (1,2,3);
一切都崩溃了:
+----+-------------+------------+-------+---------------+---------+---------+------+--------+-------------+ | id | select_type | 表| 类型| possible_keys | 关键| key_len | ref | 行| 额外的| +----+-------------+------------+-------+---------------+---------+---------+------+--------+-------------+ | 1 | 简单| 点| 范围| 主要| 主要| 4 | NULL | 3 | 使用何处| | 1 | 简单| 范围| 所有| 聚| NULL | NULL | NULL | 155183 | | +----+-------------+------------+-------+---------------+---------+---------+------+--------+-------------+
添加FORCE INDEX (poly)
没有帮助。
用于测试查询的示例数据(对不起,只有php版本,我不常见SQL程序):
//points
for($i=0;$i<=500;$i++) {
$point = mt_rand();
mysql_query('INSERT INTO points (point) VALUES (POINTFROMWKB(POINT('.$point.', 0)))');
}
$qty = 20000;
$max = mt_getrandmax();
$add = $max / $qty
$end = 0;
//polys
while($end < $max) {
$start = $end;
$end = mt_rand($start, $start + $add);
mysql_query('INSERT INTO ranges (poly) VALUES (
GEOMFROMWKB(POLYGON(LINESTRING(
POINT('.$start.', -1),
POINT('.$end.', -1),
POINT('.$end.', 1),
POINT('.$start.', 1),
POINT('.$start.', -1)
)))
)');
}
发布于 2018-10-12 13:10:39
如果您正在处理的只是正方形,我只会处理表格中的4个数字,这些数字可以被编入索引,代表顶部,左侧,高度,宽度,然后运行您的查询,其中您的点在左侧之间具有“X”坐标,顶部,顶部+高度之间的左+宽度和“Y”坐标。
发布于 2018-10-12 14:34:14
您可以通过将subselect封装在函数中来强制MySQL使用索引。
例如:
DELIMITER $$
DROP FUNCTION IF EXISTS `GetMyPolygon`$$
CREATE DEFINER=`root`@`localhost` FUNCTION `GetMyPolygon`(p POINT) RETURNS INTEGER
BEGIN
DECLARE ret INTEGER;
SET ret = (SELECT range_id FROM ranges WHERE ST_CONTAINS(poly, p) ;
RETURN ret;
END$$
如果多边形不重叠,则可以:
SELECT *, GetMyPolygon(point) FROM points
如果它们重叠,但有一些,你可以做一个类似的功能,使group_concat ...
https://stackoverflow.com/questions/-100008900
复制相似问题