简介:有没有办法提高innodb表扫描的性能?
请不要建议添加索引以避免表扫描((见下文)
innodb\u buffer\u pool\u大小占服务器内存的75%(48 gb/64gb),如果有任何变化,我将使用最新版本的percona(5.7.19)
更长:我们有600gb的最新时间序列数据(我们聚合并删除旧数据),分布在50-60个表中。所以大部分都是定期查询的“活动”数据。这些表有点大(400+数字列),许多查询都是针对其中的许多列运行的(令人震惊),这就是为什么添加索引是不切实际的(因为我们必须添加几十个索引)。最大的表每天被分区。
我完全知道这是一个应用程序/表设计问题,而不是“服务器调优”问题。我们目前正在努力显著地改变这些表的设计和查询方式,但是在这之前必须维护现有的系统,所以我正在寻找一种改进的方法来为我们争取一点时间。
我们最近拆分了这个系统,并将它的一部分移到了一个新服务器上。它以前使用的是myisam,我们尝试转移到tokudb,这看起来很合适,但是遇到了一些奇怪的问题。我们换成了innodb,但性能非常差。我得到的印象是myisam更适合表格扫描,这就是为什么,除非有更好的选择,否则我们会回到它,直到新的系统到位。
更新
所有的表都有几乎相同的结构:-时间戳-主键(varchar(20)字段)-大约15个不同类型的字段,表示可以过滤的其他辅助属性(首先还有一个适当的索引条件)-然后是大约几百个度量值(float),在200-400之间。
我已经在不改变结构本身的情况下尽可能地修剪了行的长度。主键过去是varchar(100),所有度量值过去都是双倍的,许多辅助属性的数据类型都发生了更改。
升级硬件并不是一个真正的选择。
用我需要的一组列创建小表可以帮助某些进程执行得更快。但代价是先用表扫描创建表并复制数据。如果我把它创建成一个内存表的话。据我估计,缓冲池需要几gb的空间。还有一些聚合进程定期从主表中读取尽可能多的数据,它们需要所有的列。
不幸的是,在我计划在下一个版本中解决的那些查询中有很多重复的工作。报警和聚合过程基本上是在每次插入一些行(每半小时)时重新处理一天的数据,而不是仅仅处理新的/更改的数据。
就像我说的,较大的表是分区的,所以通常只扫描一个每日分区,而不是整个表,这是一个小小的安慰。
在数据库之外实现一个将其保存在内存中的系统是可行的,但这将需要对遗留系统和开发工作进行大量更改。不如把时间花在更好的设计上。
对于与myisam相同的数据,innodb表要大得多(在我的例子中是2-3倍大)这一事实确实阻碍了性能。
2条答案
按热度按时间uelo1irk1#
它闻起来像一个有“报告”的数据仓库。通过明智地选择在什么时间段(典型的是小时或天)要聚合什么(从浮动中选择),您可以构建和维护摘要表,以便更有效地处理报表。这样做的效果是只扫描一次数据(构建摘要),而不是重复扫描。摘要表要小得多,所以报告要快得多——10倍可能是典型的。
还可以在插入原始数据时扩充汇总表(看到了吗
INSERT .. ON DUPLICATE KEY UPDATE ..
)并使用按日期划分以实现高效的
DROP PARTITION
而不是DELETE
. 分区不要超过50个。汇总表
时间序列划分
如果您想更详细地讨论,让我们从一个正在扫描的查询开始。
在我参与的各种项目中,有2到7个汇总表。
有了600gb的数据,您可能正在突破“摄取”的限制。如果是这样,我们也可以讨论。
7lrncoxx2#
myisam在表扫描方面稍微好一点,因为它比innodb存储数据更紧凑。如果查询是i/o绑定的,则扫描磁盘上较少的数据会更快。但这是一个很弱的解决方案。
您可以尝试使用innodb压缩来减小数据的大小。这可能会让你更接近myisam的大小,但你仍然是i/o绑定的,所以它会很糟糕。
最终,听起来您需要一个为olap工作负载设计的数据库,比如数据仓库。innodb和tokudb都是为oltp工作负载设计的。