mysql - 表增长后优化 MySQL 操作的最佳方法

标签 mysql database database-migration partitioning downtime

背景信息:我们运行一个电子商务网站,并试图找出处理非常频繁使用且必然包含大量记录的表的“历史”数据的最佳方法(即.订单、客户等)。

我特别关注两个具体场景:

  • 数据库迁移
  • 选择

数据库迁移

在数据库迁移的情况下,我们开始发现有时需要运行一些锁定整个表的 ALTER TABLE,如果表有这么多记录,这可能需要一段时间。当然,表上的所有操作都会暂停,直到迁移完成,这意味着我们的结账可能会因为我们将 VARCHAR(15) 更改为 VARCHAR(256) 而失败.

从 MySQL 5.6 开始,很多操作都是“INPLACE ”完成的,这意味着(从 what I understood )它们不会创建全表锁:这还可以,但仍然不完美 - 如果我们需要更改列的类型(无法就地执行)并且我们真的不想处于维护模式几分钟?

我的 super 贫民窟想法是简单地复制表(将其复制过来),然后在复制的表上执行迁移,停止写入原始表(即锁定它),将未同步的数据复制到复制一份并交换它们。我认为percona tool for zero-downtime migrations做了类似的事情,所以也许这是“最好的”方法?

意见?

选择

对于SELECT,由于大多数旧数据很少被访问,所以我想到了range-partitioning按日期(例如 2015 年之前/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

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

  • 不要在函数内“隐藏”列;优化器看不到它们:

    年份(创建时间)>= 2015 年。 --> WHERE 创建时间 >= '2015-01-01'

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

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

关于mysql - 表增长后优化 MySQL 操作的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31100552/

相关文章:

java - Mysql数据截断: Data truncation: Out of range value for column 'column' at row 1

java - Volley 超时错误...数据插入两次

database - 如何将正在使用的数据库复制到django中的其他数据库?

mysql - 将旧站点用户迁移到 Magento DB

mysql - shell命令导入表的mysql转储的一部分(从特定行)

mysql - 列中的 CONCAT 搜索

mysql - sql select 查询或 View 中的额外列

php - 多个 MySql 插入和更新未按预期运行

c# - 在 C# 中访问数据库的最佳方法(设计模式)是什么?

javascript - 使用 Electron 应用 Sqlite/Any SQL 数据库迁移 [Windows, Mac]