【问题标题】:Mysql Spatial index unusedMysql 空间索引未使用
【发布时间】:2017-04-13 09:51:54
【问题描述】:

我正在寻找能够找到从点到点的近似匹配的行(假设在 20 米内)。它可以工作,但不使用索引。

我正在尝试利用此表上的空间索引,但它似乎没有被使用(解释命令给我“possible_keys”= null)。

以下内容:

  • mysql 5.7.17
  • 表:

    CREATE TABLE `geoDirections` (
       `id` int(11) NOT NULL,
       `from` point NOT NULL,
       `to` point NOT NULL,
    ) ENGINE=InnoDB;
    ALTER TABLE `geoDirections`
        ADD PRIMARY KEY (`id`),
        ADD SPATIAL KEY `from` (`from`),
        ADD SPATIAL KEY `to` (`to`);
    
  • 大约插入了 1000000 行

我尝试了什么:

  • 使用 ST_Contains

    EXPLAIN SELECT 
       g.`from`
    FROM 
        geoDirections g
    WHERE
        ST_Contains(ST_Buffer(
              ST_GeomFromText('POINT(-2.00751 48.6547)', 4326), (0.00001*20)), g.`from`) = 1 
        AND
            ST_Contains(ST_Buffer(
              ST_GeomFromText('POINT(-2.05757 48.6338)', 4326), (0.00001*20)), g.`to`) = 1 
    

给我

    | id  |  select_type  |  table  |  partitions  |  type  |  possible_keys  |  key  |  key_len  |  ref  |  rows  |  filtered  |  Extra       |
    | 1   |  SIMPLE       |  g      |     null     |  ALL   |     null        |  null |    null   |  null | 994867 |  100.00    |  Using where |
  • 使用计算距离

    EXPLAIN SELECT
        X(g.`from`),Y(g.`from`), g.*, (
          6373 * acos (
          cos ( radians( -2.00751 ) )
          * cos( radians( X(g.`from`) ) )
          * cos( radians( Y(g.`from`) ) - radians( 48.6547  ) )
          + sin ( radians( -2.00751 ) )
          * sin( radians( X(g.`from`) ) )
        )
    ) AS distanceFrom
    FROM geoDirections g
    HAVING distanceFrom < 0.02
    

给我

    | id  |  select_type  |  table  |  partitions  |  type  |  possible_keys  |  key  |  key_len  |  ref  |  rows  |  filtered  |  Extra  |
    | 1   |  SIMPLE       |  g      |     null     |  ALL   |     null        |  null |    null   |  null | 994867 |  100.00    |  null   |
  • 即使是简单的事情

    EXPLAIN SELECT
        X(g.`from`),Y(g.`from`), g.*
    FROM geoDirections g
    WHERE X(g.`from`) = -2.00751
    

给我

    | id  |  select_type  |  table  |  partitions  |  type  |  possible_keys  |  key  |  key_len  |  ref  |  rows  |  filtered  |  Extra       |
    | 1   |  SIMPLE       |  g      |     null     |  ALL   |     null        |  null |    null   |  null | 994867 |  100.00    |  Using where |
  • 尝试将 InnoDb 转换为 MyIsam(作为不应该支持空间索引的旧 InnoDb 版本)

我错过了什么?

【问题讨论】:

  • 嗯...我想知道我的code 是否会在修复后击败它。

标签: mysql indexing gis


【解决方案1】:

Bug #76384 Spatial index not used when checking return values explicitly.

试试:

mysql> DROP TABLE IF EXISTS `geoDirections`;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE `geoDirections` (
    ->    `id` INT(11) NOT NULL,
    ->    `from` POINT NOT NULL,
    ->    `to` POINT NOT NULL
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.01 sec)

mysql> ALTER TABLE `geoDirections`
    ->     ADD PRIMARY KEY (`id`),
    ->     ADD SPATIAL INDEX (`from`),
    ->     ADD SPATIAL INDEX (`to`);
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> EXPLAIN SELECT `g`.`from`
    -> FROM `geoDirections` `g`
    -> WHERE
    ->       ST_Contains(ST_Buffer(
    ->           ST_GeomFromText('POINT(-2.00751 48.6547)', 4326), (0.00001 * 20)), `g`.`from`) 
    ->       AND
    ->       ST_Contains(ST_Buffer(
    ->           ST_GeomFromText('POINT(-2.05757 48.6338)', 4326), (0.00001 * 20)), `g`.`to`)\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: g
   partitions: NULL
         type: ALL
possible_keys: from,to
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

【讨论】:

  • 我快把我逼疯了...感谢您发现该错误。 MyISAM 上的相同错误
  • @Axi -- 它现在的运行速度有多快?
  • @RickJames 我没有检查,但它现在正在使用索引
  • ST_Buffer 仅适用于笛卡尔平面坐标 (dev.mysql.com/doc/refman/5.7/en/…)。这对你有什么作用?
猜你喜欢
  • 1970-01-01
  • 2016-05-07
  • 2020-09-29
  • 1970-01-01
  • 2012-01-04
  • 1970-01-01
  • 2012-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多