我运行一个应用程序(价格比较网站),每天需要更新包含数千万行的定价表。
基本上,我从商家下载的每个产品提要都会导致从定价表 ( WHERE merchantId = x
) 中删除数百万行,并插入数百万个新行来代替旧行。
到目前为止,我习惯于顺序下载所有提要,将它们全部插入一个临时表中,然后在单个RENAME TABLE
查询中将旧表与新表交换。
这迫使我一次更新所有商家,因此我想放弃这种方法,并且能够一次处理一个商家,删除所有记录WHERE merchantId = x
并在亚秒级查询中插入所有新记录。
我的第一个想法是使用按列表分区,每个商家一个分区。这将解决我一半的问题:我可以使用TRUNCATE PARTITION
快速删除给定商家的所有现有价格,但问题的另一半仍然存在:如何快速插入数百万个新行,而不会停机和不必要的锁定,并且不会运行桌子部分加载了几分钟?
所以我在想:是否可以创建一个与分区表结构相同的临时表,用新行填充它,一旦完成,用这个临时表交换定价表的一个分区?
任何解决此问题的建议都将不胜感激,包括不涉及分区的建议。我也考虑过MRG_MYISAM
引擎,但我不确定它是否满足我的需求。最后一点,任何存储引擎都适用于此定价表,包括非事务引擎。
在 MySQL 网站上进行了更多挖掘之后,我发现了Exchange Partitions and Subpartitions with Tables,这似乎是 MySQL 5.6 的一个新功能:
这似乎正是我要找的。
在我的服务器上运行一些基准测试后,我发现用表交换分区不是即时的,但仍然非常快:在分区表中集成表中的每 1,700,000 条记录大约需要 1 秒(分区中的记录数是取出似乎对速度没有任何影响),这非常接近我希望获得的具有几百万条记录的表的亚秒级交换。
这将与直接在分区表中插入行进行比较,在分区表中我得到大约 27,000 次插入/秒。
因此,用分区交换一个已经填满的表比直接插入分区表快大约 60 倍(对我来说,YMMV)。
甜的!