mysql geolat geolng 多索引查询
mysql geolat geolng multi indexed query
我有一个 table,其中包含字段 'lat' 和 'lng'。两者几乎都是连续的,这意味着它们不会重复太多。这让我相信为 lat 和 lng 制作多列索引不会真正帮助我。我想做的是:
同时对纬度和经度建立索引,然后执行如下查询:
select from tableName where
lat >= 13.1232 and lat <=14.123 and
lng >=-80.123 and lng <=-79.232 and
name like '%greg%'
并让 mysql 执行此过程:
select 14.1232 和 13.123 之间的所有 LAT(这应该被索引,并且很快)
在步骤#1 找到的组中,执行步骤#2:找到 lngs <=-80.123和 lngs>= -79.232(这也应该被索引并且非常快)
3.在步骤#1和#2创建的组中...执行更耗时的关键字搜索。
我该怎么做?我很确定查询的第一部分(索引纬度)正在为我缩小范围……但在那之后我不确定……这就是我一直在努力寻找的东西文档
如果您绝对希望每个 where 子句都限制结果集,那么您可以尝试这样的操作,但是 sql 优化器可能会在幕后改变一些事情。我认为一两个好的指数仍然是你最好的选择,但我相信这就是你所要求的。我推荐解释计划来优化您的查询。
select * from
(
select * from
(
select * from tableName
where lat >= 14.1232 and lat <=13.123
)
where lng >=-80.123 and lng <=-79.232
)
where name like '%greg%'
MySQL 像大多数实现一样处理传统的 B 树索引:索引帮助 仅 索引中最左边列的范围条件。
我用的类比是电话簿。如果我搜索特定的姓氏,名字对,如 "Smith, John" 索引会有所帮助。我搜索姓氏 "Smith" 很快,而在 Smiths 内部,搜索 "John" 也很快。
但是如果我搜索像 "all people whose last name begins with 'S'" 这样的范围条件,那么我会得到电话簿的一个子集,但并不是所有名为 "John" 的人都被排序在一起。它们分散在我根据姓氏选择的子集中。
正是出于这个原因,MySQL 搜索 B 树索引直到第一个范围条件,然后不再使用该索引。您仍然可以为另一个维度设置条件,但它会手动搜索与第一个维度匹配的所有行。
换句话说,即使你在(lat, long)
上有复合索引,MySQL也不会使用索引的long
部分:
select ... from tableName
where lat >= 14.1232 and lat <=13.123 /* index-assisted */
and lng >=-80.123 and lng <=-79.232 /* full scan */
and name like '%greg%' /* pattern search never uses index anyway */
(顺便说一句,你的纬度条件永远不会像你写的那样是真的,但我假设你的意思是要反转的数字。)
这使得做纬度和经度条件的效率低下,因为两者都在搜索一个值的范围。
因此,MySQL 有另一种索引,它不是 B 树索引。这是一个 SPATIAL
索引,它确实支持多个范围条件。
CREATE TABLE mytable (
name TEXT NOT NULL,
coord POINT NOT NULL,
SPATIAL INDEX (coord)
);
INSERT INTO mytable (name, coord)
VALUES ('name', ST_GeomFromText('POINT(14.0 -80)'));
SELECT name FROM mytable
WHERE MBRContains(
ST_GeomFromText('Polygon((
13.123 -80.123,
14.1232 -80.123,
14.1232 -79.232,
13.123 -79.232,
13.123 -80.123))'),
coord);
是的,这更复杂,但这是获得真正的索引优化 latitude/longitude 搜索的唯一方法。
在此处阅读更多相关信息:http://dev.mysql.com/doc/refman/5.7/en/using-spatial-data.html
我有一个 table,其中包含字段 'lat' 和 'lng'。两者几乎都是连续的,这意味着它们不会重复太多。这让我相信为 lat 和 lng 制作多列索引不会真正帮助我。我想做的是:
同时对纬度和经度建立索引,然后执行如下查询:
select from tableName where
lat >= 13.1232 and lat <=14.123 and
lng >=-80.123 and lng <=-79.232 and
name like '%greg%'
并让 mysql 执行此过程:
select 14.1232 和 13.123 之间的所有 LAT(这应该被索引,并且很快)
在步骤#1 找到的组中,执行步骤#2:找到 lngs <=-80.123和 lngs>= -79.232(这也应该被索引并且非常快)
3.在步骤#1和#2创建的组中...执行更耗时的关键字搜索。
我该怎么做?我很确定查询的第一部分(索引纬度)正在为我缩小范围……但在那之后我不确定……这就是我一直在努力寻找的东西文档
如果您绝对希望每个 where 子句都限制结果集,那么您可以尝试这样的操作,但是 sql 优化器可能会在幕后改变一些事情。我认为一两个好的指数仍然是你最好的选择,但我相信这就是你所要求的。我推荐解释计划来优化您的查询。
select * from
(
select * from
(
select * from tableName
where lat >= 14.1232 and lat <=13.123
)
where lng >=-80.123 and lng <=-79.232
)
where name like '%greg%'
MySQL 像大多数实现一样处理传统的 B 树索引:索引帮助 仅 索引中最左边列的范围条件。
我用的类比是电话簿。如果我搜索特定的姓氏,名字对,如 "Smith, John" 索引会有所帮助。我搜索姓氏 "Smith" 很快,而在 Smiths 内部,搜索 "John" 也很快。
但是如果我搜索像 "all people whose last name begins with 'S'" 这样的范围条件,那么我会得到电话簿的一个子集,但并不是所有名为 "John" 的人都被排序在一起。它们分散在我根据姓氏选择的子集中。
正是出于这个原因,MySQL 搜索 B 树索引直到第一个范围条件,然后不再使用该索引。您仍然可以为另一个维度设置条件,但它会手动搜索与第一个维度匹配的所有行。
换句话说,即使你在(lat, long)
上有复合索引,MySQL也不会使用索引的long
部分:
select ... from tableName
where lat >= 14.1232 and lat <=13.123 /* index-assisted */
and lng >=-80.123 and lng <=-79.232 /* full scan */
and name like '%greg%' /* pattern search never uses index anyway */
(顺便说一句,你的纬度条件永远不会像你写的那样是真的,但我假设你的意思是要反转的数字。)
这使得做纬度和经度条件的效率低下,因为两者都在搜索一个值的范围。
因此,MySQL 有另一种索引,它不是 B 树索引。这是一个 SPATIAL
索引,它确实支持多个范围条件。
CREATE TABLE mytable (
name TEXT NOT NULL,
coord POINT NOT NULL,
SPATIAL INDEX (coord)
);
INSERT INTO mytable (name, coord)
VALUES ('name', ST_GeomFromText('POINT(14.0 -80)'));
SELECT name FROM mytable
WHERE MBRContains(
ST_GeomFromText('Polygon((
13.123 -80.123,
14.1232 -80.123,
14.1232 -79.232,
13.123 -79.232,
13.123 -80.123))'),
coord);
是的,这更复杂,但这是获得真正的索引优化 latitude/longitude 搜索的唯一方法。
在此处阅读更多相关信息:http://dev.mysql.com/doc/refman/5.7/en/using-spatial-data.html