table 增长后优化 MySQL 操作的最佳方法

Best way to optimize MySQL operations after a table grows

背景信息:我们 运行 是一个电子商务网站,正试图找出处理 table 所使用的 "historical" 数据的最佳方式非常频繁且绑定太多记录(即订单、客户等)。

我特别关注 2 个特定场景:

数据库迁移

在数据库迁移的情况下,我们开始看到我们有时需要 运行 一些 ALTER TABLE 锁定整个 table 并且,如果 table 有这么多记录,这可能需要一段时间。当然,在迁移完成之前,table 上的所有操作都将暂停,这意味着我们的结帐可能会因为我们将 VARCHAR(15) 更改为 VARCHAR(256).[=20 而停止=]

从 MySQL 5.6 开始,完成了很多操作“INPLACE" which means (from what I understood) 他们不会创建一个完整的-table 锁:这还不错,但仍然不完美 - - 如果我们需要更改列的类型(不能执行 INPLACE)并且我们真的不想在几分钟内处于维护模式怎么办?

我的绝妙想法是简单地复制 table(复制过来),然后在复制的 table 上执行迁移,停止写入原始 table(即锁定它),将未同步的数据复制到复制的数据并交换它们。我认为 percona tool for zero-downtime migrations 做了类似的事情所以也许这就是 "best" 方法?

意见?

SELECT

对于SELECTs,由于大部分旧数据很少被访问,我想range-partitioning按日期(例如2015年之前/ post-2015年)然后将我们的大部分查询更改为获取内容 WHERE YEAR(created_at) >= 2015.

如果用户想要他的完整历史数据,那么我们会动态删除该条件。这以某种方式确保数据是 well-partitioned.

还有其他想法吗?您认为分区可能值得吗?

  • 直到 5.7.1 才能快速做到这一点:

VARCHAR size may be increased using an in-place ALTER TABLE, as in this example:

ALTER TABLE t1 ALGORITHM=INPLACE, CHANGE COLUMN c1 c1 VARCHAR(255);

  • 参见 pt-online-schema-change

  • 如果您已经设置了复制,那么您可以玩ALTERing从属游戏,然后进行故障转移。 (是的,Percona 工具在这方面很方便。)

  • 不要在函数中 'hide' 列;优化器看不到它们:

    年份(created_at) >= 2015。 --> 其中 created_at >= '2015-01-01'

  • 仅划分为 2 个分区不太可能提供任何性能优势。

  • 对某些日期(例如,TO_DAYS())的 PARTITION BY RANGE 是合理的(并且通常这样做)最终清除(通过 DROP PARTITION)旧数据。 DROP 比大的 DELETE 快得多,侵入性也小得多,仅凭该功能就可以证明分区是合理的。您提到的修剪很少会加快查询速度(除非索引很差)。 More discussion of sliding time series