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

Submitted: 19 Mar 2015 8:41 Modified: 20 Mar 2015 13:39
Reporter: Johannes Staffans Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: GIS Severity:S2 (Serious)
Version:5.6.19, 5.6.25, 5.7.8 OS:Any
Assigned to: CPU Architecture:Any
Tags: INDEX, spatial, spatial index

[19 Mar 2015 8:41] Johannes Staffans
Description:
It seems that the spatial index is not used when checking return values from spatial functions explicitly. Compare:

mysql> explain select count(*) from Region where contains(`geometry`, point(13.0, 52.0)) = 1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: Region
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 7469
Extra: Using where

mysql> explain select count(*) from Region where contains(`geometry`, point(13.0, 52.0)) \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: Region
type: range
possible_keys: geometry
key: geometry
key_len: 34
ref: NULL
rows: 1
Extra: Using where

How to repeat:
Run a query against a spatial index and check its return value explicitly, e.g. "select * from Region where contains(`geometry`, point(13.0, 52.0)) = 1"

Suggested fix:
Use spatial index also when checking return value explicitly, e.g. contains(..) = 1
[20 Mar 2015 13:39] MySQL Verification Team
Hello Johannes Staffans,

Thank you for the report.
Observed similar behavior with 5.6.25 and 5.7.8 builds.

Thanks,
Umesh
[20 Mar 2015 13:41] MySQL Verification Team
// 5.7.8

root@localhost [(none)] > create database test;
Query OK, 1 row affected (0.00 sec)

root@localhost [(none)] > use test;
Database changed
root@localhost [test] > drop table if exists t1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@localhost [test] > create table t1(a geometry not null, b geometry not null,
    -> spatial index(a),spatial index(b),key(a(25)),key(b(25)),
    -> unique key(a(25),b(25)),key(b(25),a(25)))engine=myisam;
Query OK, 0 rows affected (0.01 sec)

root@localhost [test] > drop procedure if exists p1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

root@localhost [test] >
root@localhost [test] > delimiter $
root@localhost [test] >
root@localhost [test] > create procedure p1()
    -> begin
    ->  declare iii bigint unsigned default 0;
    ->  declare continue handler for sqlexception begin end;
    ->  repeat
    ->   insert into t1 set a=point(floor(rand()*iii),floor(rand()*iii)), b=point(floor(rand()*iii),floor(rand()*iii));
    ->   set iii:=iii+1;
    ->   until iii>=5000 end repeat;
    -> end $
Query OK, 0 rows affected (0.00 sec)

root@localhost [test] >
root@localhost [test] > delimiter ;
root@localhost [test] >
root@localhost [test] > call p1();
Query OK, 1 row affected (0.35 sec)

root@localhost [test] > explain select count(*) from t1 where MBRcontains(`a`, point(505, 2648))=1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 4999
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

root@localhost [test] > explain select count(*) from t1 where MBRcontains(`a`, point(505, 2648))\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: range
possible_keys: a_3,a,a_2
          key: a
      key_len: 34
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

root@localhost [test] > explain extended select count(*) from t1 where MBRcontains(`a`, point(505, 2648))=1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 4999
     filtered: 100.00
        Extra: Using where
1 row in set, 2 warnings (0.00 sec)

root@localhost [test] > show warnings;
+---------+------+---------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                         |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1681 | 'EXTENDED' is deprecated and will be removed in a future release.                                                               |
| Note    | 1003 | /* select#1 */ select count(0) AS `count(*)` from `test`.`t1` where (mbrcontains(`test`.`t1`.`a`,<cache>(point(505,2648))) = 1) |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

root@localhost [test] > explain extended select count(*) from t1 where MBRcontains(`a`, point(505, 2648))\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: range
possible_keys: a_3,a,a_2
          key: a
      key_len: 34
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: Using where
1 row in set, 2 warnings (0.00 sec)

root@localhost [test] > show warnings;
+---------+------+---------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                   |
+---------+------+---------------------------------------------------------------------------------------------------------------------------+
| Warning | 1681 | 'EXTENDED' is deprecated and will be removed in a future release.                                                         |
| Note    | 1003 | /* select#1 */ select count(0) AS `count(*)` from `test`.`t1` where mbrcontains(`test`.`t1`.`a`,<cache>(point(505,2648))) |
+---------+------+---------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.042 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.