您观察到相同查询的后续执行运行得更快并不一定意味着查询结果正在被缓存,或者查询的后续执行正在从查询缓存中返回。
可能是在第一次执行查询时,必须访问的索引和/或数据块不在 InnoDB 缓冲池或 MyISAM 键缓存中,而必须从磁盘中检索。这些块将保留在 InnoDB 缓冲池和 MyISAM 键缓存中,完全独立于 MySQL 查询缓存。如果这些块仍在内存中,则对这些块的后续访问可以更快地返回。
通常,您不希望从 InnoDB 缓冲池或 MyISAM 键缓存中刷新块来衡量性能。相反,您希望多次运行查询,并浪费第一次执行的时间。
如果您想在 InnoDB 缓冲池或 MyISAM 键缓存中没有块开始,则关闭并重新启动 MySQL 服务器。
但即使这些块不在 InnoDB 缓冲池或 MyISAM 密钥缓存中,这些块很可能仍然在 OS 文件系统缓存的“内存”中。因此,为了确保您从磁盘读取块,您还需要刷新 OS 文件系统缓存。
以下是关于 Oracle 的 Tom Kyte (AskTom) 文章的摘录,但同样的推理也适用于其他 RDBMS 系统(包括 MySQL)。
http://www.oracle.com/technetwork/issue-archive/o43asktom-094944.html
刷新缓存
问:有没有办法刷新[缓冲区缓存]?...这对于一个接一个地尝试几种方法的调整练习很重要,但我们希望在不重新启动数据库的情况下减少缓冲区中预先存在的块的影响。
答:实际上,重要的是调优工具不能这样做。重要的是运行测试,忽略结果,然后运行两到三遍并平均这些结果。在现实世界中,缓冲区缓存永远不会没有结果。绝不。调整时,您的目标是减少逻辑 I/O (LIO),因为这样物理 I/O (PIO) 将自行处理。
考虑一下:刷新共享池和缓冲区缓存比不刷新它们更加人为。我怀疑,大多数人似乎对此持怀疑态度,因为它违背了传统智慧。我将向您展示如何执行此操作,但不是为了让您可以将其用于测试。相反,我将用它来证明为什么它是徒劳的,完全是人为的(因此会导致错误的假设)。我刚刚启动了我的电脑,我已经对一个大表运行了这个查询。我“刷新”缓冲区缓存并再次运行它: