为什么这个查询不使用 key(MySQL 5.7 spatial)?
Why doesn't this query use key(MySQL 5.7 spatial)?
我用的是MySQL5.7.10,存储引擎是InnoDB。
下面是 SQLs.
1. 创建 table
CREATE TABLE `geo` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`geo` GEOMETRY NOT NULL,
PRIMARY KEY (`id`),
SPATIAL INDEX `geo` (`geo`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1
2。插入数据
insert into geo(geo) values(ST_GeomFromText('POINT(108.875000 34.216020)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.569098 36.646357)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.550988 36.633384)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.472800 36.624116)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.487460 36.563614)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.532016 36.686191)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.319010 36.987505)'));
3。创建多边形
SET @g3 = ST_GeomFromText('Polygon((108 36.5,108 36.7,109.5 36.7,109.5 36.5,108 36.5))');
4。解释 SQL
mysql> explain select st_x(geo),st_y(geo) from geo where mbrcontains(@g3,geo)>0\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: geo
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 8
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
mysql> show warnings\G
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: /* select#1 */ select st_x(`map`.`geo`.`geo`) AS `st_x(geo)`,st_y(`map`.`geo`.`geo`) AS `st_y(geo)` from `map`.`geo` where (mbrcontains((@`g3`),`map`.`geo`.`geo`) > 0)
1 row in set (0.00 sec)
为什么这个查询不使用键?
基于此Percona post
"Spatial indexes (RTREE) are only supported for MyISAM tables. One can use the functions for InnoDB tables, but it will not use spatial keys"
起初,我想将此添加为已接受答案的评论,但后来我决定添加另一个,因为已接受答案是错误的。
InnoDB 在 5.7 中支持空间索引。使用 InnoDB 的查询跳过索引的原因是由于优化器,而不是存储引擎缺乏支持。优化器简单地决定在 InnoDB 的情况下使用索引不符合成本效益(无论出于何种原因)。要确认它向 table 添加更多行(最好是随机分布的点)并重复查询
我用的是MySQL5.7.10,存储引擎是InnoDB。
下面是 SQLs.
1. 创建 table
CREATE TABLE `geo` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`geo` GEOMETRY NOT NULL,
PRIMARY KEY (`id`),
SPATIAL INDEX `geo` (`geo`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1
2。插入数据
insert into geo(geo) values(ST_GeomFromText('POINT(108.875000 34.216020)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.569098 36.646357)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.550988 36.633384)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.472800 36.624116)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.487460 36.563614)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.532016 36.686191)'));
insert into geo(geo) values(ST_GeomFromText('POINT(109.319010 36.987505)'));
3。创建多边形
SET @g3 = ST_GeomFromText('Polygon((108 36.5,108 36.7,109.5 36.7,109.5 36.5,108 36.5))');
4。解释 SQL
mysql> explain select st_x(geo),st_y(geo) from geo where mbrcontains(@g3,geo)>0\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: geo
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 8
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
mysql> show warnings\G
*************************** 1. row ***************************
Level: Note
Code: 1003
Message: /* select#1 */ select st_x(`map`.`geo`.`geo`) AS `st_x(geo)`,st_y(`map`.`geo`.`geo`) AS `st_y(geo)` from `map`.`geo` where (mbrcontains((@`g3`),`map`.`geo`.`geo`) > 0)
1 row in set (0.00 sec)
为什么这个查询不使用键?
基于此Percona post
"Spatial indexes (RTREE) are only supported for MyISAM tables. One can use the functions for InnoDB tables, but it will not use spatial keys"
起初,我想将此添加为已接受答案的评论,但后来我决定添加另一个,因为已接受答案是错误的。
InnoDB 在 5.7 中支持空间索引。使用 InnoDB 的查询跳过索引的原因是由于优化器,而不是存储引擎缺乏支持。优化器简单地决定在 InnoDB 的情况下使用索引不符合成本效益(无论出于何种原因)。要确认它向 table 添加更多行(最好是随机分布的点)并重复查询