未使用空间索引

Posted

技术标签:

【中文标题】未使用空间索引【英文标题】:Spatial Index not being used 【发布时间】:2016-05-07 17:23:29 【问题描述】:

我在 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 参考:空 行数: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

【问题讨论】:

【参考方案1】:

很遗憾,ST_Distance() &lt; 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。另一方面,又大又丑的 concat 项目产生了一条从边界矩形的西南角到东北角的对角线。使用您的数据点和十英里半径,它看起来像这样。

LINESTRING(37.8785 -94.2564,38.1684 -93.8884)

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

第三,ST_Distance(),在 MySQL 中,不处理大圆经纬度计算。 (PostgreSQL 有一个更全面的GIS extension。)MySQL 就像平地里的烙饼一样愚蠢。它假定几何对象中的点以平面几何表示。所以 ST_Distance() &lt; 10.0 带有 lng/lat 点做了一些奇怪的事情。

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

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

【讨论】:

哇。多么丰富的信息啊!今天晚些时候会仔细看看这个。完全有道理。谢谢奥利!我一直在寻找这些信息。 在我今天早上跑去参加我女儿的篮球比赛之前必须做一个小测试(今晚会更深入一些)。因此,即使我在 10 英里内输入已知的纬度/经度,它也不会返回任何匹配项。我已经尝试了几个已知点,但仍然没有。 如果表中的点使用 SRID(空间参考标识符),请确保添加与 GeomFromText() 函数的第二个(可选)参数相同的 SRID:例如 GeomFromText('...', 4326) 当使用 4326 的 SRID(或类似的我猜)时,空间数据被定义为 X=lon 和 Y=lat,所以需要使用@latpoint 而不是@lngpoint,反之亦然,在上面的代码中。 上面边界坐标的计算不太准确:janmatuschek.de/…

以上是关于未使用空间索引的主要内容,如果未能解决你的问题,请参考以下文章

oracle查看索引表空间的使用情况

如何减少DB上一个表的Unused空间

如何监控ORACLE索引使用与否

Mysql空间索引

空间索引 - 各数据库空间索引使用报告

oracle, 表索引占用空间非常大, 15g以上了, 重建索引后所用空间缩减为原来不到1/5, 这是啥原因?