5

我的查询有问题,需要 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 <1 秒。

我正在使用 Godaddy VPS Windows Server 2008 Economy

表格示例:

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
4

2 回答 2

1

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

于 2013-02-19T17:11:57.987 回答
1

首先,我假设gps_unit_location它真的是一张桌子而不是一个视图。其次,我还假设您已经多次运行这两个查询,所以缓存不是解释。(缓存将是您运行第一个查询,它将表加载到页面缓存中,第二个从内存而不是磁盘读取。)

你有索引gps_unit_location(idgps_unit)吗?记录范围很广吗?如果这些问题的答案是“是”,那么可能会发生以下情况。

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

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

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

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

于 2013-02-19T17:18:07.530 回答