查询性能;不确定发生了什么

时间:2013-02-19 17:04:05

标签: mysql sql performance database-performance

我的查询出现问题需要17秒才能执行(350k行):

SELECT idgps_unit, MAX(dt) 
         FROM gps_unit_location
        GROUP BY 1

解释

1   SIMPLE  gps_unit_location   index       fk_gps2 5       422633  

玩完之后,我带来了这个需要1秒的解决方案:

Select idgps_unit, MAX(dt) from (
SELECT idgps_unit,  dt
         FROM gps_unit_location
) d1
Group by 1

说明:

1   PRIMARY <derived2>  ALL                 423344  Using temporary; Using filesort
2   DERIVED gps_unit_location   index       gps_unit_location_dt_gpsid  10      422617  Using index

现在我很困惑 - 为什么查询#2很快,而查询#1似乎是相同的查询,似乎写得更有效。

Index1:DT,Index2:idgps_unit,Index3:idgps_unit + DT

执行时间一致;查询#1总是需要17-19秒;而#1&lt; 1sec。

我正在使用Godaddy VPS Windows Server 2008经济版

表示例:

id | idgps_unit | dt | location
1 | 1 | 2012-01-01 | 1
2 | 1 | 2012-01-02 | 2
3 | 2 | 2012-01-03 | 3
4 | 2 | 2012-01-04 | 4
5 | 3 | 2012-01-05 | 5

2 个答案:

答案 0 :(得分:1)

我会说你的索引没有正确设置,你的第二个查询是一种内部查询,它有效地创建了自己的内部索引组,如果这有意义的话!

答案 1 :(得分:1)

首先,我假设gps_unit_location实际上是一个表而不是一个视图。其次,我还假设您已多次运行两个查询,因此缓存不是解释。 (缓存是你运行第一个查询,它将表加载到页面缓存中,第二个从内存而不是磁盘读取。)

你有gps_unit_location(idgps_unit)的索引吗?记录非常广泛吗?如果这些问题的答案为“是”,则可能发生以下情况。

如果是这样,您可能会对索引有一个奇怪的问题。你会认为索引会加速这样的查询。但它的作用是按顺序查找idgps_id中的值。如果索引不包含日期,则数据库需要从每个页面获取数据。如果表不适合内存,那么这通常会导致缓存未命中 - 也就是加载页面的时间。

相比之下,如果表格很宽并且引擎进行全表扫描,那么它可以在表格中拉链并提取感兴趣的两个字段。它把它们放在一边。如果它们相对于整个表格较小,那么对它们进行排序可能只需要很少的时间。瞧,查询结束得更快。

我的猜测是第二个结构会删除索引的使用。

顺便说一下,您可以通过将索引更改为gps_unit_location(idgps_unit, dt)来解决此问题。通过在索引中包含该字段,查询不必加载数据。