使用MySQL定期对100 GB以上的表进行多向联接吗?


11

背景
我创建了一个Web应用程序,希望能够合理扩展。我知道我不是Google或Twitter,但是我的应用为每个用户使用了大量的数据,因此对数据的要求很高。我想准备好合理扩展,而不必稍后重新构建所有架构。

我认为自己是软件开发人员,而不是数据库专家。这就是为什么我在这里发布。希望有更多数据库专业知识的人能给我建议。

由于用户数量相对较大,但没有Facebook号码,因此我希望拥有一个如下数据库:

一个“大桌子”:

  • 2.5亿条记录
  • 20列
  • 大约100 GB的数据
  • 具有索引的bigint(20)外键
  • 有一个索引varchar(500)string_id列
  • 有一个int(11)“值”列

其他4个表格:

  • 每一千万条记录
  • 每个约2-4 GB数据
  • 每个表都有4-8列
  • 一栏是datetime date_created
  • 一列是varchar(500)string_id列
  • 每个表中的一或两列将在联接中被选择

这些表之一用于存储平均值-其架构为bigint(20)id,varchar(20)string_id,datetime date_created和float average_value

我想做的 -两个相对昂贵的查询:

  1. 计算新的平均值:

    • 使用外键,从大表中选择多达几百万条单独的记录。
    • 计算新的平均值,按string_id分组。
    • 将结果插入平均值表。
    • 按照当前的构造,此查询使用两个联接。
  2. 为服务用户创建非规范化的只读记录:

    • 使用外键从大表中选择1,000-40,000条记录中的任意位置。
    • 通过字符串id列与最新记录上的其他四个表连接。
    • 将结果插入到非规范化表中。
    • 这些记录供前端使用以向用户显示信息。
    • 按照当前的构造,此查询使用四个联接。

我计划在批处理后端数据库上运行所有这些昂贵的查询,这些查询会将其结果推送到处理用户请求的实时前端数据库服务器上。这些查询将定期运行。我还没有决定多久。平均查询可能每天进行一次。反规范化查询将需要更加频繁-也许每隔几分钟。

目前,这些查询中的每一个查询都在一台非常低端的计算机上的MySQL中运行,该计算机的数据集在“大表”中具有10万条记录。我既担心扩展能力,又担心扩展成本。

问题

  1. 这种方法听起来不错吗?从全局角度看,这显然有什么问题吗?
  2. RDBMS是正确的工具,还是我应该看看Hadoop系列中的其他“大数据”解决方案?我倾向于使用RDBMS,因为数据是结构化的并且很好地适合于关系模型。但是从某种意义上说,据我了解,我可能不再能够使用RDBMS。真的吗?什么时候需要此开关?
  3. 能行吗 这些查询能否在合理的时间内运行?我可以等待几个小时来查询#1,但是查询#2应该在几分钟内完成。
  4. 从硬件角度我应该考虑什么?我的RAM和CPU瓶颈可能是什么?我认为在RAM中保留索引很重要。还有什么我应该考虑的吗?
  5. 在某个时候,我可能必须对数据进行分区并使用多个服务器。我的用例看起来已经属于该类别了,还是可以在一段时间内垂直扩展一台计算机?这样可以处理10倍的数据吗?100倍?

这是很难彻底回答的。也许您最好从总体上研究MySQL查询性能特征,以便您知道可以期望什么。您可以始终做的一件事当然是在服务器中放入20个磁盘,这样您就可以以3GB / s的速度读取数据。但是我认为您是在寻求完全基于软件的解决方案。
usr

Answers:


4

您是否尝试过堆放更多数据并对其进行基准测试?10万行无关紧要。尝试250M或500M,就像您期望的那样,并查看瓶颈在哪里。

如果您仔细注意局限性并尝试利用系统的优势,那么RDBMS可以做很多事情。它们在某些方面非常出色,而在其他方面则很糟糕,因此您需要进行实验以确保它是正确的。

对于某些批处理作业,您实际上无法敲打平面文件,无法将数据加载到RAM中,使用一系列循环和临时变量将其粉碎,然后转储结果。MySQL将永远无法达到这样的速度,但是如果正确调整和正确使用它,其速度可能会达到一个数量级。

您要做的是研究如何对数据进行分区。您是否拥有大量的数据,但交叉链接方式过多,无法拆分,还是有自然的分区方法?如果可以对其进行分区,那么您将不会有一个包含一堆行的表,但是可能会有很多明显较小的行。较小的表具有较小的索引,往往会表现更好。

从硬件的角度来看,您需要进行测试以查看平台的性能。有时记忆是必不可少的。其他时候是磁盘I / O。这实际上取决于您对数据的处理方式。您需要密切注意CPU的使用情况,并寻找大量的IO等待知道问题出在哪里。

只要有可能,就将数据分散到多个系统中。如果您觉得自己很勇敢,可以使用MySQL Cluster,或者简单地启动许多独立的MySQL实例,每个实例使用有意义的分区方案存储完整数据集的任意部分。


@tadman感谢您的建议。我意识到实际尝试无可替代。我没有用2.5亿行作为基准,因为我首先要确保我的方法没有明显错误。听起来好像没有。另外,获取大量数据并以某种切实可行的方式进行处理是我还没有弄清楚如何解决的挑战。我确实有一些可能的方法来对数据进行分区。我想我接下来将仅尝试扩展我的数据,并查看它如何在不同的检查点(1M,10M,100M等
。– xnickmx 2012年

1

汇总表。

每天,计算当天数据的汇总信息。将其放在“摘要”表中。对他们进行查询。轻松达到10倍的速度。

进一步讨论,请提供

  • 显示创建表(现在显示)
  • 表格大小(您已提到)
  • 建议的选择

一些明显的事情...

  • 很少需要BIGINT。占用8个字节。INT UNSIGNED取4,允许值为0.4十亿。还有MEDIUMINT等。
  • “事实”表上的多个索引通常是一个严重的性能问题,尤其是对于INSERT。你在那里有问题吗?
  • DATETIME是8个字节;时间戳是4
  • 明确的外键约束很好,但代价昂贵
  • JOIN可能会或可能不是性能问题;需要查看SELECT和CREATE。
  • 对于“大型” MySQL数据库而言,100GB是一个不错的大小。我怀疑它可以在没有Hadoop等的情况下正常工作。我现在处理一个这样的数据库-即使数据非常复杂,大多数UI页面在不到一秒钟的时间内响应。
  • 您会在某个时候“清除”数据吗?(这导致了PARTITIONING的主要用例。)

“更小->更可缓存->更快


0

为了提供您的前端数据,除非一直有插入的gobs和gobs,否则您真的无法使用触发器插入与后端保持同步但已优化以处理数据的物化视图中进行插入。当然,在这些触发器中,您需要将联接等保持最小。我使用的一种策略是将这些插入/更新排队到中间表中,然后每隔一分钟左右发送一次。发送一条记录比4 GB记录要容易得多。即使您可以快速找到要查找的记录,4 GB的数据也需要花费很长时间来流式传输。

我同意塔德曼的观点。最好的方法是在所需的系统上使用所需的数据对它进行分析。


正如我在文章中提到的那样,视图依赖于一个查询,该查询在具有数千万条记录的表之间使用四个联接,因此我真的看不到物化视图将如何提供帮助。
xnickmx 2012年

对于此大小的数据库,触发器可能不够快。每秒发生多少个INSERT?
瑞克·詹姆斯

1
@xnickmx如果插入/更新的次数不多,则触发器使轻松/高效地保持非规范化数据同步。如果需要更快地进行插入/更新,请使用以下内容将其放入队列:blog.shlomoid.com/2008/04/…或自行烘焙。这样,您无需加入现有的1亿行表就可以获取新数据,因为在触发触发器时,您可以利用事实,即您知道新数据,并且可以将其作为tx的一部分进行反规范化或将其排队以便稍后进行反规范化。
wes.stueve 2012年

@RickJames同意。您必须考虑这种策略的插入量以及它们必须处理的速度。
wes.stueve 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.