背景信息:我们运营一个电子商务网站,并试图找出处理非常频繁使用的表格的“历史”数据的最佳方法,并且绑定的数据也包含大量记录(即订单,客户等。)
我特别关注两个具体情况:
在数据库迁移的情况下,我们开始看到我们有时需要运行一些锁定整个表的ALTER TABLE,如果表有这么多记录,这可能需要一段时间。当然,桌面上的所有操作都会暂停,直到迁移完成为止,这意味着我们的结帐可能会因为我们将VARCHAR(15)
更改为VARCHAR(256)
而失败。
从MySQL 5.6开始,许多操作都是“INPLACE”,这意味着(来自what I understood)他们不会创建一个全表锁:这是好的但仍然不完美 - - 如果我们需要更改列的类型(不能执行INPLACE)并且我们真的不希望处于维护模式几分钟怎么办?
我的超级贫民窟的想法是简单地复制表(复制它),然后在复制的表上执行迁移,停止写入原始表(即锁定它),将未同步的数据复制到复制一个并交换它们。我认为percona tool for zero-downtime migrations做了类似的事情,也许这是“最好的”方法?
评论
对于SELECTs
,因为很少访问大多数旧数据,所以我按日期(例如2015年之前/ 2015年之后)考虑了range-partitioning然后更改了我们的大部分数据查询以获取内容WHERE YEAR(created_at) >= 2015
。
如果用户想要他的完整历史数据,那么我们将动态删除该条件。这以某种方式确保数据为well-partitioned。
还有其他想法吗?您认为分区可能值得吗?
答案 0 :(得分:0)
使用就地ALTER TABLE可以增加VARCHAR大小,如 这个例子:
ALTER TABLE t1 ALGORITHM = INPLACE,CHANGE COLUMN c1 c1 VARCHAR(255);
请参阅pt-online-schema-change
。
如果已经设置了复制,那么您可以玩ALTERing
奴隶游戏,然后进行故障转移。 (是的Percona工具在这个领域很方便。)
不要隐藏'功能内的列;优化器无法看到它们:
WHERE YEAR(created_at)> = 2015。 - > WHERE created_at> =' 2015-01-01'
仅分区为2个分区不太可能带来任何性能优势。
对某个日期的PARTITION BY RANGE
合理(通常已完成)(例如,TO_DAYS()
),以便最终清除(通过{{1旧数据。 DROP PARTITION
比大DROP
更快且侵入性更小,仅此功能证明了分区的合理性。您提到的修剪很少加快查询速度(除非索引很差)。 More discussion of sliding time series