首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MySQL 8不使用空间索引?

MySQL 8不使用空间索引?
EN

Database Administration用户
提问于 2020-02-27 18:16:30
回答 3查看 1.5K关注 0票数 2

我有一个问题,无论我做什么,我都不能让MySQL使用一个空间索引。

下面这样的查询需要5秒的时间!

有没有办法强迫它使用索引呢?

代码语言:javascript
运行
复制
WITH ranked_reports AS (
    SELECT
        station_id,
        raw_text,
        observation_time,
        RANK() OVER ( PARTITION BY station_id ORDER BY observation_time DESC ) order_rank 
    FROM
        METAR 
    WHERE
        ST_Distance_Sphere (
            geo_point,
        ST_GeomFromText ( 'POINT(51.85 -0.79)', 4326 )) <= 100 * 1609.34 
    ) SELECT
    * 
FROM
    ranked_reports 
WHERE order_rank =1

解释查询

代码语言:javascript
运行
复制
+----+-------------+------------+------------+------+---------------+-------------+---------+-------+--------+----------+-----------------------------+
| id | select_type | table      | partitions | type | possible_keys | key         | key_len | ref   | rows   | filtered | Extra                       |
+----+-------------+------------+------------+------+---------------+-------------+---------+-------+--------+----------+-----------------------------+
|  1 | PRIMARY     | <derived2> | NULL       | ref  | <auto_key0>   | <auto_key0> | 8       | const |     10 |   100.00 | NULL                        |
|  2 | DERIVED     | METAR      | NULL       | ALL  | NULL          | NULL        | NULL    | NULL  | 585814 |   100.00 | Using where; Using filesort |
+----+-------------+------------+------------+------+---------------+-------------+---------+-------+--------+----------+-----------------------------+

表结构

代码语言:javascript
运行
复制
CREATE TABLE `METAR` (
  `station_id` varchar(5) NOT NULL,
  `station_iata` varchar(5) DEFAULT NULL,
  `observation_time` datetime NOT NULL,
  `latitude` float(255,2) DEFAULT NULL,
  `longitude` float(255,2) DEFAULT NULL,
  `raw_text` varchar(255) DEFAULT NULL,
  `temp_c` float(255,1) DEFAULT NULL,
  `dewpoint_c` float(255,1) DEFAULT NULL,
  `wind_dir_degrees` int(255) DEFAULT NULL,
  `wind_speed_kt` int(11) DEFAULT NULL,
  `wind_gust_kt` int(11) DEFAULT NULL,
  `visibility_statute_mi` float(255,2) DEFAULT NULL,
  `altim_in_hg` float(255,2) DEFAULT NULL,
  `altim_in_hPa` float(255,0) DEFAULT NULL,
  `sea_level_pressure_mb` float(255,0) DEFAULT NULL,
  `wx_string` varchar(255) DEFAULT NULL,
  `sky_condition` mediumtext,
  `flight_category` varchar(255) DEFAULT NULL,
  `three_hr_pressure_tendency_mb` float DEFAULT NULL,
  `maxT_c` float(255,0) DEFAULT NULL,
  `minT_c` float(255,0) DEFAULT NULL,
  `maxT24hr_c` float DEFAULT NULL,
  `minT24hr_c` float(255,0) DEFAULT NULL,
  `precip_in` float(255,0) DEFAULT NULL,
  `pcp3hr_in` float(255,0) DEFAULT NULL,
  `pcp6hr_in` float(255,0) DEFAULT NULL,
  `pcp24hr_in` float(255,0) DEFAULT NULL,
  `snow_in` float(255,0) DEFAULT NULL,
  `vert_vis_ft` int(255) DEFAULT NULL,
  `time_added` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `geo_point` point NOT NULL /*!80003 SRID 4326 */,
  PRIMARY KEY (`station_id`,`observation_time`),
  KEY `IDX_Station` (`station_id`) USING BTREE,
  KEY `IDX_Deletion` (`observation_time`) USING BTREE,
  KEY `IDX_IATA` (`station_iata`,`observation_time`) USING BTREE,
  SPATIAL KEY `IDX_Spatial` (`geo_point`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
EN

回答 3

Database Administration用户

发布于 2020-05-01 18:31:49

您的查询

代码语言:javascript
运行
复制
WHERE
    ST_Distance_Sphere (
        geo_point,
    ST_GeomFromText ( 'POINT(51.85 -0.79)', 4326 )) <= 100 * 1609.34 
)

在MySQL中,您必须使用MBR函数来使用索引.

所以不要用ST_Distance_Sphere

代码语言:javascript
运行
复制
MBRContains( ST_Buffer( ST_SRID(POINT(51.85 -0.79), 4326), 100 * 1609.34), geog )
票数 2
EN

Database Administration用户

发布于 2020-02-27 19:04:37

您需要将SRID添加到列定义中:

SRID属性使空间列SRID受到限制,这具有以下含义:该列只能包含具有给定SRID的值。尝试使用不同的SRID插入值会产生错误。优化器可以在列上使用空间索引。见8.3.3节,“空间索引优化”。没有SRID属性的空间列不受SRID限制,并接受任何SRID的值。但是,优化器在修改列定义以包含SRID属性之前不能对它们使用空间索引,这可能要求首先修改列内容,以便所有值都具有相同的SRID。

票数 1
EN

Database Administration用户

发布于 2021-10-26 12:14:19

当比较where子句中空间函数的返回值时,MySQL只忽略索引。此bug在https://bugs.mysql.com/bug.php?id=76384中报告,在我的本地env中用8.0.27进行确认。

你在这个问题中的目标可以转化为另一个目标:搜索距离给定点(LNG,LAT)的半径单位距离内的点。这可以由ST_Contains/ST_Within来完成。

由于ST_Contains/ST_Within返回1或0,所以可以忽略where子句中的= 1,它将只选择1的值。where子句应该如下所示:

代码语言:javascript
运行
复制
WHERE ST_Contains(
  ST_Buffer(ST_SRID(Point(LNG, LAT), 4326), RADIUS),
  geo_point
)
票数 0
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/260757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档