如何使用 innodb 提高表扫描的性能



简介:有没有办法提高InnoDB表上的表扫描性能?

请不要建议添加索引以避免表扫描。(见下文)

innodb_buffer_pool_size位于服务器内存的 75% (48 GB/64GB) 我正在使用最新版本的Percona(5.7.19),如果这改变了什么

更长:我们有 600Gb 的最近时间序列数据(我们聚合并删除旧数据),分布在 50-60 个表中。 因此,其中大部分是定期查询的"活动"数据。 这些表有点大(400+ 数字列),许多查询针对其中许多列运行(令人震惊),这就是为什么添加索引是不切实际的(因为我们必须添加几十个)。 每天对最大的表进行分区。

我完全知道这是一个应用程序/表设计问题,而不是"服务器调整"问题。 我们目前正在努力显着改变这些表的设计和查询方式,但必须维护现有系统,直到发生这种情况,所以我正在寻找一种方法来改进事情,为我们争取一点时间。

我们最近拆分了这个系统,并将其的一部分移动到了新服务器上。 它以前使用MyISAM,我们尝试迁移到TokuDB,这似乎很合适,但遇到了一些奇怪的问题。 我们切换到InnoDB,但性能真的很差。 我的印象是MyISAM在表扫描方面更好,这就是为什么,除非有任何更好的选择,否则我们将回到它,直到新系统到位。

更新

所有表的结构几乎相同: -时间戳 -主键 (varchar(20) 字段) -大约 15 个各种类型的字段,代表可以过滤的其他次要属性(首先是适当的索引条件) -然后大约几百个措施(浮点数),在 200-400 之间。

我已经在不更改结构本身的情况下尽可能多地修剪了行长度。 主键曾经是 varchar(100),所有度量值过去都是双精度值,许多辅助属性的数据类型都发生了变化。

升级硬件实际上不是一种选择。

仅包含我需要的列集创建小表将有助于某些进程更快地执行。 但代价是先使用表扫描创建该表并复制数据。 也许如果我将其创建为内存表。 根据我的估计,缓冲池需要几 GB。 此外,还有一些聚合进程会定期从主表中读取尽可能多的数据,并且它们需要所有列。

不幸的是,这些查询中有很多重复的工作,我计划在下一个版本中解决。 警报和聚合过程基本上在每次插入某些行(每半小时)时重新处理一整天的数据,而不仅仅是处理新的/更改的数据。

就像我说的,较大的表是分区的,所以通常是扫描每日分区而不是整个表,这是一个小小的安慰。

实现一个系统来将其保存在数据库之外的内存中是可行的,但这需要对遗留系统和开发工作进行大量更改。 不妨把时间花在更好的设计上。

对于与MyISAM相同的数据,InnoDB表要大得多(在我的情况下是2-3倍)确实阻碍了性能。

MyISAM在表扫描方面要好一点,因为它比InnoDB更紧凑地存储数据。如果查询是 I/O 密集型查询,则扫描磁盘上的数据会更快。但这是一个非常弱的解决方案。

您可以尝试使用 InnoDB 压缩来减小数据大小。这可能会让你更接近MyISAM的大小,但你仍然是I/O绑定的,所以它会很糟糕。

最终,听起来您需要一个专为 OLAP 工作负载设计的数据库,例如数据仓库。InnoDB和TokuDB都是为OLTP工作负载而设计的。

它闻起来像带有"报告"的数据仓库。 通过明智地选择要在哪个时间段(小时或天是典型值)内聚合的内容(从浮点数中选择),您可以构建和维护摘要表,这些汇总表可以更有效地为报告工作。 这具有仅扫描一次数据(以构建摘要)的效果,而不是重复扫描。 摘要表要小得多,因此报告要快得多 - 10 倍可能是典型的。

还可以在插入原始数据时扩充摘要表。 (见INSERT .. ON DUPLICATE KEY UPDATE ..)

并使用按日期分区以实现高效的DROP PARTITION而不是DELETE。 分区不要超过 50 个。

汇总表

时序分区

如果您想更详细地讨论,让我们从现在正在扫描的查询之一开始。

在我参与过的各种项目中,有 2 到 7 个摘要表。

对于 600GB 的数据,您可能会突破"摄取"的限制。 如果是这样,我们也可以讨论一下。

相关内容

  • 没有找到相关文章

最新更新