非常大的SQL表的注意事项?

时间:2010-01-04 23:38:58

标签: mysql

我正在构建一个广告服务器。这是一个个人项目,我试图给我的老板留下深刻的印象,我喜欢任何形式的关于我的设计的反馈。我已经实现了下面描述的大部分内容,但重构永远不会太晚:)

这是一项提供横幅广告(http://myserver.com/banner.jpg http://myserver.com/clicked链接)的服务,并提供有关数据子集的报告。

对于每次投放的广告展示和每次点击,我都需要记录一行(ID,值)[其中value是此交易的现金价值;例如 - 每1美元CPM每个服务横幅广告$ 0.001,或点击+ 25美元;我的输出全部基于每次展示的收入[缩写为EPC]:(SUM(value)/COUNT(impressions)),但是在数据的子集上,例如“每次展示的收入,其中浏览器=='Firefox'”。我们的目标是输出类似“您的整体EPC为0.50美元,但浏览器=='Firefox',您的EPC为1.00美元”,以便最终用户可以快速查看其数据中的重要因素。

因为非常大量的这些子集(数万个),并且报告输出只需要包含摘要数据,所以我用背景cron预先计算每个子集的EPC任务,并将这些汇总值存储在数据库中。一旦在每2-3次命中,Hit需要查询Hits表以获取访问者的其他近期命中(例如“查找最后一次命中的REFERER”),但通常,每次Hit只执行一次INSERT,以便保持响应我已经将应用程序拆分为3台服务器[bgprocess,mysql,hitserver]。

现在,我将所有这些结构化为3个规范化表:Hits,Events和Visitors。访问者对于每个访问者会话是唯一的,每次访问者加载横幅或点击时都会记录命中,并且事件映射从访问者到命中的不同的多对多关系(例如,事件是“横幅Y处的访客X” “,这是唯一的,但可能有多个Hits)。我将所有匹配数据保存在同一个表中的原因是,虽然我的上述示例仅描述了“横幅展示次数 - >点击次数”,但我们还会跟踪“点击次数 - >像素点火”,“像素点火 - >第二次点击“和”第二次点击 - >销售页面像素“。

我的问题是Hits表快速填满,并且随着大小线性减慢。我的测试数据只有几千次点击,但我的后台处理速度已经放慢了。我可以投入更多的服务器,但在启动它的alpha之前,我想确保我的逻辑是合理的。

所以我问你这样的大师,你会如何构建这些数据?我是否疯狂尝试预先计算所有这些表格?由于我们很少需要访问超过一小时的Hit记录,我是否有利于将Hits表拆分为ProcessedHits(包含所有历史数据)和UnprocessedHits(包含〜last hours的数据),或者将Hit.at Date列索引为make这多余了?

这可能需要一些详细说明,对不起,如果我不清楚的话,我到目前为止已经连续工作了大约3周:) TIA所有输入!

2 个答案:

答案 0 :(得分:1)

你应该能够以这样的方式构建这样的应用程序,使其不会随着点击次数的增加而线性减速。

从你的说法来看,听起来你有两个主要的潜在性能瓶颈。第一个是插入。如果您可以在表的末尾进行插入,那么可以最大限度地减少碎片并最大化吞吐量。如果他们处于中间位置,性能将随着碎片的增加而受到影响。

第二个区域是聚合。无论何时进行重要聚合,请注意不要使所有内存缓冲区被清除以为传入数据腾出空间。尽量减少必须完成聚合的频率,并明智地了解如何对事物进行分组和计数,以最大限度地减少磁头移动(或者考虑使用SSD)。

您可能还可以完全基于传入数据而不是新查询在Web层上执行某些累积,如果服务器在收集的数据写入之前关闭之前可能会出现某种回退DB。

您使用的是INNODB还是MyISAM?

以下是一些表现原则:

  1. 尽量减少从Web层到数据库的往返行程
  2. 最小化聚合查询
  3. 通过在可能的情况下插入表格末尾来最小化磁盘碎片并最大化写入速度
  4. 优化硬件配置

答案 1 :(得分:0)

通常,您有详细的“累加器”表,其中记录是实时写入的。正如您所发现的那样,它们会迅速变大。您的后端通常会将这些原始记录汇总到多维数据集或其他“存储桶”中,然后您可以从中创建报告。一旦您确定了您要报告和/或开帐单的内容,您的多维数据集可能会定义自己。

如果这是一个真实的项目,请不要忘记欺诈检测。