繁体   English   中英

MySQL查询性能调优

[英]MySQL query performance tuning

我正在尝试对具有约100万条记录的表进行查询。 该表及其索引的结构为:

CREATE TABLE `table` (
    `Id` int(11) NOT NULL,
    `Name` varchar(510) DEFAULT NULL,
    `Latitude` float NOT NULL DEFAULT '0',
    `Longitude` float NOT NULL DEFAULT '0',
    PRIMARY KEY (`Latitude`,`Longitude`,`Id`),
    KEY `IX_Latitude_Longitude` (`Latitude`,`Longitude`),
    KEY `IX_Latitude` (`Latitude`),
    KEY `IX_Longitude` (`Longitude`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

我正在运行以下查询:

SELECT m.Id, m.Name, sqrt(69.1 * (m.Latitude - :latitude) * 69.1 * (m.Latitude - :latitude) +
                     53.0 * (m.longitude - :longitude) * 53.0 * (m.longitude - :longitude)) as Distance,
m.Latitude as Latitude, m.Longitude as Longitude
FROM table m
WHERE sqrt(69.1 * (m.Latitude - :latitude) * 69.1 * (m.Latitude - :latitude)
      + 53.0 * (m.longitude - :longitude) * 53.0 * (m.longitude - :longitude)) < :radius
ORDER BY  sqrt(69.1 * (m.Latitude - :latitude) * 69.1 * (m.Latitude - :latitude) +
          53.0 * (m.longitude - :longitude) * 53.0 * (m.longitude - :longitude)) desc
LIMIT 0, 100

这假设将返回特定半径内的所有记录(距离计算信息: http : //www.meridianworlddata.com/Distance-Calculation.asp

但是查询需要很多时间...这是我得到的解释计划:

id|select_type |table|type|possible_keys|key   |key_len|ref   |rows   |Extra
1 |SIMPLE      |m    |ALL |{null}       |{null}|{null} |{null}|1264001|Using where; Using filesort

我究竟做错了什么? 我需要添加哪个索引才能使查询使用它而不是表扫描? 我需要更改表结构吗?

您在WHERE子句中使用函数,因此它将始终导致表扫描。 数据库无法对函数结果建立索引。 我认为您最好的选择是在尝试评估距离算法之前想出一些方法来限制结果。

例如,对于给定的位置,您可以知道可能落在您设置的距离内的最小和最大纬度,因此请先过滤该纬度。 纬度约为69英里,因此,如果您的搜索半径为50英里,则超过0.725纬度的任何地方都不可能落在您所在位置的50英里之内。 由于这只是一个数字比较,因此WHERE m.latitude > (:latitude - 0.725) AND m.latitude < (:latitude + 0.725)而不是对函数的调用,数据库将能够使用您的索引对其进行评估。

经度更加复杂,因为每个度数的距离都取决于该位置在北/南偏远的地方,但是取决于您要投入多少工作量,您也可以对经度进行相同的操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM