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

And*_*rew 5 mysql sql performance database-performance

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

SELECT idgps_unit, MAX(dt) 
         FROM gps_unit_location
        GROUP BY 1
Run Code Online (Sandbox Code Playgroud)

说明

1   SIMPLE  gps_unit_location   index       fk_gps2 5       422633  
Run Code Online (Sandbox Code Playgroud)

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

Select idgps_unit, MAX(dt) from (
SELECT idgps_unit,  dt
         FROM gps_unit_location
) d1
Group by 1
Run Code Online (Sandbox Code Playgroud)

说明:

1   PRIMARY <derived2>  ALL                 423344  Using temporary; Using filesort
2   DERIVED gps_unit_location   index       gps_unit_location_dt_gpsid  10      422617  Using index
Run Code Online (Sandbox Code Playgroud)

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

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

执行时间是一致的; 查询#1总是需要17-19秒; 而#1 <1秒.

我正在使用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
Run Code Online (Sandbox Code Playgroud)

Gor*_*off 1

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

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

如果是这样,您可能会遇到一个奇怪的索引问题。您可能会认为索引会加速此类查询。不过,它的作用是按顺序查找值idgps_id。如果索引不包含日期,则数据库需要从每个页面获取数据。如果该表无法装入内存,那么这通常会导致缓存未命中,即加载页面的时间过长。

相比之下,如果表很宽并且引擎执行全表扫描,那么它可以快速浏览表并提取感兴趣的两个字段。这让他们站在一边。如果它们相对于整个表来说很小,那么对它们进行排序可能会花费很少的时间。瞧,查询完成得更快。

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

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