我在网站上有一个mysql选择语句用于搜索,但是当网站非常繁忙时会出现性能问题。下面的查询从具有超过100k记录的表中搜索广告,在给定的纬度和经度范围内(25英里以内),并按距离排序。英里数可能因用户而异。
问题在于,我认为它很慢,因为它对表中所有记录进行计算,而不是在纬度和经度范围内的记录。是否可以修改此查询,使where子句仅选择25英里以内的广告?我已经了解了边界框和空间索引,但我不确定如何将它们应用于此查询,我是否需要添加where子句来选择与纬度和经度25英里半径的记录,如何实现?
问题在于,我认为它很慢,因为它对表中所有记录进行计算,而不是在纬度和经度范围内的记录。是否可以修改此查询,使where子句仅选择25英里以内的广告?我已经了解了边界框和空间索引,但我不确定如何将它们应用于此查询,我是否需要添加where子句来选择与纬度和经度25英里半径的记录,如何实现?
SELECT
adverts.*,
round(sqrt((((adverts.latitude - '53.410778') * (adverts.latitude - '53.410778')) * 69.1 * 69.1) + ((adverts.longitude - '-2.97784') * (adverts.longitude - '-2.97784') * 53 * 53)), 1) as distance
FROM
adverts
WHERE
(adverts.type_id = '3')
HAVING
DISTANCE < 25
ORDER BY
distance ASC
LIMIT 120,10
编辑:更新以包含表模式,请注意表格更为复杂,因此查询也更为复杂,但我已删除对此问题不必要的内容。
CREATE TABLE `adverts` (
`advert_id` int(10) NOT NULL AUTO_INCREMENT,
`type_id` tinyint(1) NOT NULL,
`headline` varchar(50) NOT NULL,
`description` text NOT NULL,
`price` int(4) NOT NULL,
`postcode` varchar(7) NOT NULL,
`latitude` float NOT NULL,
`longitude` float NOT NULL,
PRIMARY KEY (`advert_id`),
KEY `latlon` (`latitude`,`longitude`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
当我在mysql语句上执行explain时,行数设置为67900,这比25英里半径内的实际数量要多得多,额外设置为“使用where; 使用filesort”。
查询需要0.3秒,这非常慢,特别是当网站每秒接收到大量请求时。