我的理解是,一个新的RDS实例将根据需要从快照中“分页”,如此处所述的EC2卷。
这是目前造成我痛苦:我正在一个新的testing实例上运行一个大的查询; 运行需要10-15分钟,但最后一个小时才能运行。 这个实例具有1,000GB的存储容量,所以3000 IOPS,但是在控制台中我看到<100 IOPS(有时甚至小于20读取IOPS)。
通常我会使用mysqldump进行完整的数据库备份并将其发送到/dev/null – 但需要12-18个小时。 我过去曾经在多个表上做过表扫描查询,希望这些IO能够并行发生。
有谁知道更好的方法来预热音量?
不幸的是,强制块被分页的唯一方法是获取它们,并且已经有多种方法来实现这一点。
因为看起来没有比我已经使用的更简单的方法,所以我决定评估这些方法。
对于testing环境,我为每个方法创build了一个实例:r3.large(2个VCPU,15 GB RAM),每个实例使用相同的快照。 这些实例有1000 GB的磁盘,所以应该能够保持3000 IOPS。
整个数据库包含几百个表,从几百行到几百万行(主要用于logging的几个表,但可能涉及一些报告查询)。
我select了两张表格进行评估:我们的“用户”表,其中包含2000万行,过于宽,“联动”表也包含20MM行,但只有两列。
在加载之后,我对用户表运行了两个查询:一个通过合计非索引数字字段来强制进行表扫描,另一个对索引列(应该遍历整个索引)执行聚合操作。 我没有对链接表执行查询,因为它似乎没有提供更多的信息。
所有时间格式为H:MM:SS(小时:分钟:秒),并且来自单次运行。 我还使用Cloudwatch指标(通常平均5-15分钟)跟踪读写IOPS。
我们的数据库使用MySQL,但是我相信一般的方法都适用于任何DBMS。
mysqldump CONNECTION_OPTIONS --compress DATABASE TABLES > /dev/null
mysqldump程序用于备份数据库或单个表。 它检索所有的表数据并将其写入StdOut以及DDL以重新创build表及其索引。
由于我不关心实际备份表,所以我将输出redirect到/dev/null 。 由于我不想被networking--compress ,我使用--compress选项。 即便如此,我运行在同一个亚马逊EC2实例上,以保持亚马逊数据中心内的所有networkingstream量。
这种方法的主要缺点是不会碰到索引块。
Users Linkage --------------------------------------------- | time to touch blocks | 00:53:38 | 00:03:02 | | read IOPS | < 150 | 150+ | | table-scan | 00:01:29 | | | index aggregate | 00:00:15 | |
与testing查询非常相似,这种方法是从非索引字段中汇总数据的简单select。 我为“触摸”查询select了一个不同的字段,而不是“testing”查询。
与转储操作一样,这只访问表数据块。 我可以通过某种forms的索引聚合来扩展它以访问索引块,但是我认为这与我的需求不太相关。
Users Linkage --------------------------------------------- | time to touch blocks | 00:59:12 | 00:03:31 | | read IOPS | 150 | 150 | | table-scan | 00:02:04 | | | index aggregate | 00:00:19 | |
OPTIMIZE TABLE命令将重buildInnoDB表和索引,释放进程中的空间。 这是特定于MySQL,但我会考虑Postgres VACUUM命令是相似的,我敢肯定有其他数据库系统的等效命令。
这对于我们的大桌子来说可能是一个不公平的考验,因为它有很多的更新,毫无疑问在多年的生活中从未被优化。 如果我们定期进行优化,数字可能会更低。
Users Linkage ---------------------------------------------- | time to touch blocks | 02:01:36 | 00:03:44 | | read IOPS | 100 | 150 | | write IOPS | 500+ | 1000+ | | table-scan | 00:00:05 | | | index aggregate | 00:00:01 | |
你会注意到我添加了一条写入IOPS的行。 而且,这些查询时间不是印刷错误:它们比其他的要快一个数量级以上。 我怀疑这是因为块被caching在内存中(我可能应该重新触摸块之间的实例和执行查询)。
OPTIMIZE对于大型表格来说要慢得多,并且使用太多的写入IOPS。 但是,如果我在Postgres上,那么VACUUM可能是一个有效的select,假设源数据库是经常清理的。
所有行select和mysqldump之间的区别很小,可能是由于networking或虚拟机负载。 但是, mysqldump执行起来要容易得多,因为全行select需要一些思路来select合适的查询。
运行这些testing后,我创build了一个新的实例,并启动了10个并发的mysqldump会话(随机分配它们之间的表)。 一些观察:
正如我对这个问题进行了更多的思考,我认为我的痛苦主要是因为我正在使用这个实例来testing报告负载。 如果它是一个OLTP实例,我怀疑我可以将它转换成服务,尽量减less痛苦(尽pipe性能较慢)。 但是,同样的痛苦会影响到只读副本,也许更重要的是因为只有在系统负载很重时才会出现另一个副本。
长期以来,我只能希望亚马逊能够看到增加一个“快速初始化”操作,并行触及卷的块。