MySQL和一个包含100多万行的表

use*_*820 18 mysql

我有一些超过1亿行的表.我每个月大约有20到40万行.

此时一切似乎都很好: - 所有插入都很快 - 所有选择都很快(他们使用索引而不使用复杂的聚合)

但是,我担心两件事,我在某处读过: - 当一个表有几亿行时,可能会有慢插入,因为重新平衡索引可能需要一段时间(二叉树) - 如果索引不适合内存,则可能需要一段时间才能从磁盘的不同部分读取它.

任何评论都将受到高度赞赏.任何建议我如何避免它或如何/如果/当它发生时我将如何修复/缓解问题将非常感激.

(我知道我们应该在某一天开始进行分片)

先感谢您.

tad*_*man 26

今天是你应该考虑分片或分区的那一天,因为如果你今天有100MM的行,并且你每月大约需要30MM,那么你将在三个月内将它的大小增加一倍,并且可能在之前再增加一倍这一年结束了.

在某些时候,您将遇到数据库太大而无法迁移的事件视界.要么磁盘上没有足够的工作空间来切换到备用架构,要么在需要再次运行之前没有足够的停机时间来执行迁移.然后,随着它越来越慢,你会永远坚持下去.

表上写入活动的性能很大程度上取决于索引的维护难度.您索引的数据越多,写入的惩罚就越多.索引的类型都是相关的,有些比其他更紧凑.如果您的数据被轻微编入索引,您通常可以在事情开始变得非常缓慢之前获得更多记录,但这种降级因素在很大程度上取决于您的系统配置,硬件和IO容量.

请记住,InnoDB,你应该使用的引擎,有很多调整参数,许多人将它设置为非常可怕的默认值.看看分配给它的内存,并确保你正确地做到了这一点.

如果您有任何方法对这些数据进行分区,例如按月,按客户或基于业务逻辑不会改变的其他因素,那么数据本质上是不相关的,您将有许多简单的选项.如果不是,你将不得不做出一些艰难的决定.

您现在要做的一件事就是模拟表中的1G行的表现.创建足够大,适当变化的测试数据量,然后查看它在负载下的性能.您可能会发现这不是问题,在这种情况下,不用担心再过几年.如果没有,请立即开始恐慌,并在数据变得太大而无法拆分之前努力寻求解决方案.

数据库性能通常以相当线性的方式降级,然后在某些时候它从悬崖上掉下来.你需要知道这个悬崖的位置,以便在你击中之前知道你有多少时间.当索引无法适应内存并且磁盘缓冲区拉得太薄而无法使用时,性能的急剧下降通常会出现.

  • 它归结为测试,测试和更多测试。您可以观察到一些变量,这些变量告诉您​​MySQL如何使用内存,但这是一个漫长而复杂的讨论。有整本关于这个主题的书。通常,如果磁盘上索引文件的大​​小超过了InnoDB的可用内存,您肯定会遇到麻烦,但是耗尽通常在此之前发生,这是由于对其施加了其他压力。 (2认同)

Ric*_*mes 6

我将尝试解决OP和其他答复者提出的观点。这个问题只触及表面;这个答案也是如此。我们可以更深入地挖掘更有针对性的问题。

  • 万亿行变得很危险。100M不一定有问题。
  • 分区并不是性能的灵丹妙药。它有用的主要情况是当您需要清除“旧”数据时。(比无数行DROP PARTITION快得多。)DELETEing
  • INSERTsAUTO_INCREMENT PRIMARY KEY永远不会放慢速度。这适用于任何时间键和/或一小组“热点”。示例PRIMARY KEY(stock_id, date)仅限于您拥有的库存数量的热点。
  • INSERTs使用 UUIDPRIMARY KEY会变得越来越慢。但这适用于任何“随机”密钥。
  • 二级索引也遇到了与 PK 相同的问题,但时间更晚。这是因为它取决于 BTree 的大小。(由 PK 排序的数据 BTree 通常大于每个辅助键。)
  • 仅当插入是“随机”时(与 UUID 一样),索引(包括 PK)是否“适合内存”才重要。
  • 对于数据仓库应用程序,通常建议提供汇总表,而不是“事实”表上的额外索引。这产生的“报告”查询速度可能快 10 倍。
  • 盲目使用AUTO_INCREMENT 可能达不到最佳效果。
  • 百万行表的数据或索引的 BTree 深度约为 3 层。对于一万亿行,有 6 个级别。这个“级别数”对性能有一定的影响。
  • 不使用二叉树;相反,InnoDB 使用 BTree(实际上是 B+Tree)。
  • InnoDB 基本上不需要太多努力就能保持其 BTree 平衡。别担心。(并且不要使用OPTIMIZE TABLE。)
  • 所有活动都在 16KB 块(数据或索引)上完成,并在 RAM(在 buffer_pool 中)中完成。表和索引都不会“加载到 RAM 中”,至少不会明确地作为一个整体单元。
  • 复制对于读取扩展很有用。(并且可以在 MySQL 中轻松使用。)
  • 分片对于写入扩展很有用。(这是一个 DIY 任务。)
  • 根据经验,在大型表上保留一半的磁盘空间用于各种管理目的。
  • 在表进入多 GB 大小范围之前,重新考虑数据类型和规范化是明智的做法。
  • InnoDB 中的主要可调参数(目前)是innodb_buffer_pool_size,它(对于初学者来说)应该是可用 RAM 的 70% 左右。
  • Row_format=compressed 通常不值得使用。
  • YouTube、Facebook、Google 等“超越”了本次问答中讨论的任何内容。他们使用数千台服务器、定制软件等。

如果您想讨论您的具体应用程序,让我们看看一些细节。不同的应用程序需要不同的技术。

我的博客,提供有关上述许多主题的更多详细信息: http://mysql.rjweb.org