我有一个问题,无论我做什么,我都不能让MySQL使用一个空间索引。
下面这样的查询需要5秒的时间!
有没有办法强迫它使用索引呢?
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
解释查询
+----+-------------+------------+------------+------+---------------+-------------+---------+-------+--------+----------+-----------------------------+
| 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 |
+----+-------------+------------+------------+------+---------------+-------------+---------+-------+--------+----------+-----------------------------+
表结构
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;
发布于 2020-05-01 18:31:49
您的查询
WHERE
ST_Distance_Sphere (
geo_point,
ST_GeomFromText ( 'POINT(51.85 -0.79)', 4326 )) <= 100 * 1609.34
)
在MySQL中,您必须使用MBR函数来使用索引.
所以不要用ST_Distance_Sphere
,
MBRContains( ST_Buffer( ST_SRID(POINT(51.85 -0.79), 4326), 100 * 1609.34), geog )
发布于 2020-02-27 19:04:37
您需要将SRID添加到列定义中:
SRID属性使空间列SRID受到限制,这具有以下含义:该列只能包含具有给定SRID的值。尝试使用不同的SRID插入值会产生错误。优化器可以在列上使用空间索引。见8.3.3节,“空间索引优化”。没有SRID属性的空间列不受SRID限制,并接受任何SRID的值。但是,优化器在修改列定义以包含SRID属性之前不能对它们使用空间索引,这可能要求首先修改列内容,以便所有值都具有相同的SRID。
发布于 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子句应该如下所示:
WHERE ST_Contains(
ST_Buffer(ST_SRID(Point(LNG, LAT), 4326), RADIUS),
geo_point
)
https://dba.stackexchange.com/questions/260757
复制相似问题