在某些情况下不使用空间索引

时间:2018-11-27 19:02:10

标签: mysql indexing mariadb geospatial spatial

我在MariaDB 10.3数据库中有2个表。

注意:为了不扭曲结果,所有查询都是在MariaDB服务器上关闭查询缓存的情况下完成的。

  1. 位置-该表包含2个 FLOAT 列,其中 Lat Lng 具有GPS坐标。我这里大约有3.000.000点。
  2. 城市-该表包含约7.000个城市的列表,这些城市的边界由名称为 Boundaries POLYGON 列类型指定。我还具有 SPATIAL 索引,该列的名称也为 Boundaries

我正在尝试执行此SQL查询-到目前为止,对于最后25条记录(排序是通过主键完成的,因此可以立即工作并且不会成为瓶颈):

SELECT Places.Id, Cities.Name
    FROM Places
    LEFT JOIN Cities ON ST_CONTAINS(Cities.Boundaries, POINT(Places.Lat, Places.Lon)))
    ORDER BY Places.Id LIMIT 25

此查询占用我的计算机2.7秒,这是绝对错误的。我尝试执行此查询的解释,发现 possible_keys 列中是 Boundaries ,而<< em> key 列,这意味着空间索引将被完全忽略。

现在,我到目前为止所做的尝试:

  1. 使用 FORCE INDEX 关键字不会更改任何内容-密钥仍未使用
  2. 即使LIMIT 1耗时0.109秒,它也会线性扩展至25条记录所需的时间
  3. 用子查询替换JOIN不会做任何更改-查询需要相同的时间
  4. Places 表中创建具有本机POINT格式的预缓存纬度/经度的专用 POINT 列,并在查询中使用它代替 POINT()不会做任何改变

现在有趣的是:

当我从一个像POINT(Places.Lat, Places.Lon)这样的随机位置将POINT(49.472240, 17.086672)替换为常数时,它突然使用了空间索引,没有问题。甚至 EXPLAIN 都表明使用了索引,并且查询花费了0.000秒!

我的意思是,对数据库的最后一个位置执行LIMIT 1查询需要0.109秒,并且MariaDB不使用空间索引,但是当我保持该查询不变时,只需在POINT()函数中替换Lat和Lon具有常量值-与数据库中的最后一个常量相同,查询突然使用索引,耗时0.000秒。这两个查询的结果是相同的。

问题:为什么使用列中的数据而不是常量会阻止MariaDB使用空间索引?如何更改此查询,以便能够使用空间索引将所有300万个点相对快速地连接到城市?我不希望它能在几毫秒内加入,但是要花上几年的时间,如果1条记录花费了0.1秒的时间却没有索引。

0 个答案:

没有答案