2010-09-23 115 views
1

我有一个表foo它记录鸟类的目击。 foo_id是它的PK,其他有关的列是s_date,纬度和经度。 species_id是它的FK。我有索引s_date,经度和纬度species_id。表富有2000万条记录并且在不断增加。 以下查询给出了给定纬度/长度的前10个最新物种目击。查询花费的时间太多(有时候超过10分钟)。如何优化它?我正在使用mysql。优化查询

SELECT species_id, max(s_date) 
FROM foo 
WHERE latitude >= minlat 
    AND latitude <= maxlat 
    AND longitude >= minlon 
    AND longitude <= max lon 
GROUP BY species_id 
ORDER BY MAX(s_date) DESC LIMIT 0, 10; 
+0

另外适当的索引,有没有一大堆优化... – 2010-09-23 19:11:13

+0

是species_id一个真正的FK,与它的索引和约束,或FK只是它的昵称? – Midhat 2010-09-23 19:13:00

+0

我认为FK“昵称”更适合它的定义 – androidharry 2010-09-23 19:24:54

回答

0

我知道你在提到的字段上有单独的索引。你可能想尝试(latitude, longitude)增加一个综合指数(又名多列索引):

CREATE INDEX ix_foo_lat_lng ON foo (latitude, longitude); 

您可能需要您的查询运行EXPLAIN看什么指数(ES),MySQL的使用。从MySQL Manual :: How MySQL Uses Indexes报价:

假设你发出以下声明SELECT

mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2; 

如果col1col2存在多列索引,适当的行可以直接取出。如果在col1col2上存在单独的列索引,优化程序将尝试使用Index Merge optimization,或者尝试通过确定哪个索引找到更少的行并使用该索引来获取行来尝试查找最具限制性的索引。

您还可能有兴趣在检查出下面的介绍:

笔者介绍了如何使用Haversine Formula在MySQL的命令接近和限制您的搜索到一个定义的范围。他还介绍了如何使用经纬度列上的传统索引来避免此类查询的全表扫描。


PDF Version

+0

感谢您的答案。有关通过按部件顺序优化组的任何建议? – androidharry 2010-09-23 19:32:50

+0

@androidharry:如果'(纬度,经度)'上的复合索引起作用,并且将结果集限制为几行,那么'GROUP BY'应该会自动很快。现在它很慢,因为(查看上面的注释)你的查询只是使用'longitude'索引,所以中间结果集非常大。 – 2010-09-23 19:39:02

+0

我已经在使用类似于演示文稿中所示的内容。我从http://www.movable-type.co.uk/scripts/latlong-db.html找到了这个公式。它正在使用地球半径进行计算,而在演示中正在使用69英里。我想知道哪一个是正确的? – androidharry 2010-09-24 06:08:05