我试图在可接受的时间内在大型数据库上运行查询。我正在考虑优化查询本身(例如Clarification of join order for creation of temporary tables),这使我无法完成查询(使用20小时上限)来完成查询,但是时间过长了。仍然不能接受。
在实验中,我发现了以下我想要理解的奇怪行为:我希望在2年的时间范围内进行查询。如果我尝试直接运行它,那么它仍然无法在10分钟内完成,我可以进行测试。如果我将它减少到该范围的前6个月,它将很快完成。如果我然后通过在范围内添加几个月来逐步重新运行查询(即运行8个月,然后运行10个月,直到整整2年),每次连续尝试都将完成,我可以自行启动能够获得我想要的整整两年。
我怀疑这可能是由于MySQL服务器缓存了结果,但这似乎与文档不符:
如果稍后收到相同的语句,服务器将从查询缓存中检索结果,而不是再次解析和执行语句。
http://dev.mysql.com/doc/refman/5.7/en/query-cache.html
关键词似乎是"相同,"我所做的其他阅读改进了查询相同的明显要求。 (The docs甚至表明对查询的比较是文字的,即用" SELECT" vs." select"写的逻辑等效查询不匹配。)在我的例如,每个后续查询都包含上一个查询的完整范围,但其中没有两个是完全相同的。
此外,表格会在一夜之间更新。因此,在昨天结束的时候,我们在19秒内完成了2年的完整查询,大概是因为我们在那时获得了至少一次完整结果。今天我们不能让查询再次运行,这似乎与昨晚更新表时无效的缓存一致。
所以问题:是否有一些特殊情况允许服务器在这种情况下缓存?如果是,那记录在哪里?如果没有,关于还有什么会导致这种行为的任何建议?
答案 0 :(得分:1)
是的,有一个缓存可以优化(一般)对硬盘的访问。它实际上是每个基于存储的数据库系统中非常重要的一部分,因为从硬盘驱动器读取数据(或写入例如临时数据)通常是大多数查询最相关的瓶颈。
对于InnoDB,这称为InnoDB Buffer Pool:
InnoDB维护一个称为缓冲池的存储区域,用于在内存中缓存数据和索引。了解InnoDB缓冲池如何工作,并利用它来将频繁访问的数据保存在内存中,是MySQL调优的一个重要方面。有关InnoDB缓冲池如何工作的信息,请参阅InnoDB缓冲池LRU算法。
您可以配置InnoDB缓冲池的各个方面以提高性能。
- 理想情况下,您可以将缓冲池的大小设置为尽可能大的值,从而为服务器上的其他进程留出足够的内存,而无需过多的分页。 缓冲池越大,InnoDB就像内存数据库一样,从磁盘读取数据一次,然后在后续读取期间从内存中访问数据。请参见第15.6.3.2节“配置InnoDB缓冲区”泳池大小“。
关于buffer pool,它如何运作以及如何optimize it可以(并且已经)写过书籍,所以我会停在那里,让你留下这个关键字并引用你文档。
基本上,您的后续读取将数据添加到缓存中,可以重复使用,直到它被其他数据替换(在您的情况下第二天发生)。因为(对于MySQL),这可以是所涉及的表的任何读取,并且不一定是您可能复杂的查询,它可能使您更容易“预取”。
虽然以下附带免责声明,因为如果您更改配置,它显然会对您的服务器产生负面影响:默认的MySQL配置非常(非常)保守,例如对于大多数15岁以下的服务器来说,innodb_buffer_pool_size
系统设置太低了,所以可能需要查看一下您的配置(或让系统管理员检查一下)。
答案 1 :(得分:0)
我们做了一些实验,包括检查@Solarflare在答案中提到的系统效果。在我们的例子中,我们得出结论,明显的缓存是真实的,但它根本与MySQL无关。它取而代之的是Linux磁盘缓存。我们能够通过在获得结果之前和之前手动刷新缓存并比较时间来验证这一点。