未使用空间索引
Spatial Index not being used
我在 GEO_LOCATION 列上有一个空间索引,但是当我执行 EXPLAIN 时,它没有显示正在使用该索引。谁能告诉我为什么?
EXPLAIN
SELECT AsText(GEO_LOCATION)
FROM PERSON
WHERE ST_Distance(POINT(-94.0724223,38.0234332), GEO_LOCATION) <= 10
id: 1
select 类型:简单
table:人
类型:全部
possible_keys: 空
键:NULL
key_len: 空
参考:NULL
行数:612602
额外:使用 where
这是我的环境:
服务器类型:MariaDB
服务器版本:10.1.8-MariaDB - mariadb.org 二进制分发
协议版本:10
服务器字符集:UTF-8 Unicode (utf8)
Apache/2.4.17 (Win32) OpenSSL/1.0.2d PHP/5.6.14
数据库客户端版本:libmysql - mysqlnd 5.0.11-dev - 20120503
PHP 扩展:mysqli 文档
PHP 版本:5.6.14
很遗憾 ST_Distance() < threshold
isn't a sargable 搜索条件。为满足此查询,MySQL 必须计算 table 中每一行的函数值,然后将其与阈值进行比较。所以它必须进行完整的 table 扫描(或者可能是完整的索引扫描)。
要利用索引来加速此查询,您将需要一个边界框标准。查询更详细,但也更快。假设您的几何图形中的 x/y 点以度数表示 latitude/longitude,则该查询可能如下所示:
set @latpoint = 38.0234332;
set @lngpoint = -94.0724223;
set @r = 10.0; /* ten mile radius */
set @units=69.0; /* 69 statute miles per degree */
SELECT AsText(geo)
FROM markers
WHERE MbrContains(GeomFromText(
CONCAT('LINESTRING(', @latpoint-(@r/@units),' ',
@lngpoint-(@r /(@units* COS(RADIANS(@latpoint)))),
',',
@latpoint+(@r/@units) ,' ',
@lngpoint+(@r /(@units * COS(RADIANS(@latpoint)))),
')')),
geo)
这是如何工作的?一方面,MbrContains(bound,item) function is sargable。另一方面,大而丑陋的 concat 项目会产生一条从边界矩形的西南角到东北角的对角线。使用您的数据点和十英里半径,它看起来像这样。
LINESTRING(37.8785 -94.2564,38.1684 -93.8884)
当您在 MbrContains()
的第一个参数中使用该对角线的 GeomFromText()
渲染时,它用作边界矩形。 MbrContains()
然后可以利用漂亮的四叉树几何索引。
第三,ST_Distance()
,在MySQL中,不处理大圆经纬度计算。 (PostgreSQL has a more comprehensive GIS extension.) MySQL 就像平原上的烙饼一样笨。它假定您的几何对象中的点以平面几何表示。所以 ST_Distance() < 10.0
和 lng/lat 点做了一些奇怪的事情。
此查询生成的结果中存在一个缺陷;它 returns 边界框中的所有点,而不仅仅是指定半径内的点。这可以通过单独的距离计算来解决。我已经写完了所有这些 in some detail here.
注意:对于GPS分辨率的经纬度,32位FLOAT
数据具有足够的精度。 DOUBLE
是 MySQL 的地理扩展所使用的。当您使用度数时,小数点后五位以上超出了 GPS 的精度。 DECIMAL()
不是 lat/lng 坐标的理想数据类型。
我在 GEO_LOCATION 列上有一个空间索引,但是当我执行 EXPLAIN 时,它没有显示正在使用该索引。谁能告诉我为什么?
EXPLAIN
SELECT AsText(GEO_LOCATION)
FROM PERSON
WHERE ST_Distance(POINT(-94.0724223,38.0234332), GEO_LOCATION) <= 10
id: 1
select 类型:简单
table:人
类型:全部
possible_keys: 空
键:NULL
key_len: 空
参考:NULL
行数:612602
额外:使用 where
这是我的环境:
服务器类型:MariaDB
服务器版本:10.1.8-MariaDB - mariadb.org 二进制分发
协议版本:10
服务器字符集:UTF-8 Unicode (utf8)
Apache/2.4.17 (Win32) OpenSSL/1.0.2d PHP/5.6.14
数据库客户端版本:libmysql - mysqlnd 5.0.11-dev - 20120503
PHP 扩展:mysqli 文档
PHP 版本:5.6.14
很遗憾 ST_Distance() < threshold
isn't a sargable 搜索条件。为满足此查询,MySQL 必须计算 table 中每一行的函数值,然后将其与阈值进行比较。所以它必须进行完整的 table 扫描(或者可能是完整的索引扫描)。
要利用索引来加速此查询,您将需要一个边界框标准。查询更详细,但也更快。假设您的几何图形中的 x/y 点以度数表示 latitude/longitude,则该查询可能如下所示:
set @latpoint = 38.0234332;
set @lngpoint = -94.0724223;
set @r = 10.0; /* ten mile radius */
set @units=69.0; /* 69 statute miles per degree */
SELECT AsText(geo)
FROM markers
WHERE MbrContains(GeomFromText(
CONCAT('LINESTRING(', @latpoint-(@r/@units),' ',
@lngpoint-(@r /(@units* COS(RADIANS(@latpoint)))),
',',
@latpoint+(@r/@units) ,' ',
@lngpoint+(@r /(@units * COS(RADIANS(@latpoint)))),
')')),
geo)
这是如何工作的?一方面,MbrContains(bound,item) function is sargable。另一方面,大而丑陋的 concat 项目会产生一条从边界矩形的西南角到东北角的对角线。使用您的数据点和十英里半径,它看起来像这样。
LINESTRING(37.8785 -94.2564,38.1684 -93.8884)
当您在 MbrContains()
的第一个参数中使用该对角线的 GeomFromText()
渲染时,它用作边界矩形。 MbrContains()
然后可以利用漂亮的四叉树几何索引。
第三,ST_Distance()
,在MySQL中,不处理大圆经纬度计算。 (PostgreSQL has a more comprehensive GIS extension.) MySQL 就像平原上的烙饼一样笨。它假定您的几何对象中的点以平面几何表示。所以 ST_Distance() < 10.0
和 lng/lat 点做了一些奇怪的事情。
此查询生成的结果中存在一个缺陷;它 returns 边界框中的所有点,而不仅仅是指定半径内的点。这可以通过单独的距离计算来解决。我已经写完了所有这些 in some detail here.
注意:对于GPS分辨率的经纬度,32位FLOAT
数据具有足够的精度。 DOUBLE
是 MySQL 的地理扩展所使用的。当您使用度数时,小数点后五位以上超出了 GPS 的精度。 DECIMAL()
不是 lat/lng 坐标的理想数据类型。