mysql - 未使用空间索引

标签 mysql indexing mariadb spatial

我在 GEO_LOCATION 列上有一个空间索引,但是当我执行 EXPLAIN 时,它没有显示该索引正在被使用。谁能告诉我为什么吗?

EXPLAIN 
SELECT AsText(GEO_LOCATION) 
FROM PERSON 
WHERE ST_Distance(POINT(-94.0724223,38.0234332), GEO_LOCATION) <= 10

id:1
选择类型:简单
表:人
类型:全部
可能的键:NULL
键:NULL
key_len: NULL
引用:NULL
行:612602
额外:使用位置

这是我的环境:
服务器类型:MariaDB
服务器版本:10.1.8-MariaDB - mariadb.org 二进制发行版
协议(protocol)版本: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 不是sargable搜索标准。为了满足这个查询,MySQL 必须计算表中每一行的函数值,然后将其与阈值进行比较。因此它必须进行全表扫描(或者可能是全索引扫描)。

要利用索引来加速此查询,您将需要一个边界框标准。查询更加复杂,但速度也快得多。假设几何中的 x/y 点代表纬度/经度(以度为单位),该查询可能如下所示:

   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)函数 sargable 。另一方面,丑陋的大连接项会产生一条从边界矩形的西南角到东北角的对角线。使用您的数据点和十英里半径,它看起来像这样。

LINESTRING(37.8785 -94.2564,38.1684 -93.8884)

当您使用GeomFromText()MbrContains() 的第一个参数中的对角线的渲染它用作边界矩形。 MbrContains()然后可以利用漂亮的四叉树几何索引。

第三,ST_Distance() ,在 MySQL 中,不处理大圆纬度和经度计算。 ( PostgreSQL 有一个更全面的 GIS extension 。)MySQL 的愚蠢就像平原上的烙饼。它假设几何对象中的点以平面几何表示。所以ST_Distance() < 10.0与 lng/lat 点做一些奇怪的事情。

此查询生成的结果存在一个缺陷;它返回边界框中的所有点,而不仅仅是指定半径内的点。这可以通过单独的距离计算来解决。我已经把这些写下来了 in some detail here .

注意:对于 GPS 分辨率纬度和经度,32 位 FLOAT数据有足够的精度。 DOUBLE这是 MySQL 的地理扩展所使用的。当您以度为单位时,小数点后五位以上超出了 GPS 的精度。 DECIMAL()不是纬度/经度坐标的理想数据类型。

关于mysql - 未使用空间索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35093608/

相关文章:

mysql - 复合索引不适用于范围查询

mysql - node.js、mysql、日期时间和时间偏移

mysql - 如果没有找到记录,sql 将值设为零

mysql - Dapper 是否支持在单个查询中插入多行?

php - mySQL插入如果id存在否则发送错误给用户,我可以使用什么方法?

MySQL + phpMyAdmin decimal 每次默认为零

mysql - blob 列上的慢查询分组

mysql - 如何确认我已禁用表索引?

python - 使用python脚本创建SQL表出错

php - jQuery PHP 仅适用于 3 个参数