我在建一个广告服务器。这是一个我想给老板留下深刻印象的私人项目,我喜欢任何形式的关于我设计的反馈。我已经实现了下面描述的大部分内容,但重构永远不会太迟:)
这是一个提供横幅广告(http://myserver.com/banner.jpg链接到http://myserver.com/clicked)并提供数据子集报告的服务。
对于每个广告印象服务和每次点击,我需要记录一行,其中有(id,value)[其中value是该交易的现金价值;例如,每服务一条横幅广告的成本为1美元每分钟0.001美元,或点击一次的成本为0.25美元];我的输出都基于每个印象的收益[缩写为epc]:(SUM(value)/COUNT(impressions))
,但基于子集比如“浏览器=Firefox时的每印象收益”。目标是输出类似于“您的总epc是0.50美元,但是在browser=='firefox',您的epc是1.00美元”的内容,以便最终用户能够快速看到其数据中的重要因素。
由于这些子集的数量非常大(数以万计),并且报告输出只需要包含摘要数据,所以我使用后台cron任务预计算每个子集的epc,并将这些摘要值存储在数据库中。每点击2-3次,点击就需要查询点击表中访问者最近的其他点击(例如“查找上一次点击的引用者”),但通常,每次点击只执行一次插入,因此为了减少响应时间,我将应用程序分成3个服务器(bgprocess、mysql、hitserver)。
现在,我已经将所有这些结构为3个标准化表:点击率、事件和访问者。每个访问者会话的访问者都是唯一的,每次访问者加载横幅或单击时都会记录一次点击,事件将访问者与点击之间的不同多对多关系映射到不同的点击(例如,示例事件是“横幅y处的访问者x”,这是唯一的,但可能有多个点击)。我将所有点击数据保存在同一个表中的原因是,虽然上面的示例只描述了“横幅显示->点击量”,但我们也在跟踪“点击量->像素激发”、“像素激发->第二次点击量”和“第二次点击量->销售页面像素”。
我的问题是hits表很快就满了,并且随着大小而线性地变慢。我的测试数据只有几千次点击,但我的后台处理速度已经开始放缓。我可以投入更多的服务器,但在启动alpha之前,我想确保我的逻辑是正确的。
所以我问你,大师,你会如何组织这些数据?我是不是疯了想把这些表都预算出来?因为我们很少需要访问超过一小时的命中记录,所以将hit s表拆分为processedhits(包含所有历史数据)和unprocessedhits(包含~last hour's data)会有好处吗?或者将hit.at date列编入索引会使这一操作变得多余吗?
这可能需要一些详细说明,对不起,如果我不清楚,我已经连续工作了3个星期了,到目前为止:)所有的输入蒂亚!
最佳答案
你应该能够建立这样一个应用程序的方式,它不会放缓与点击数线性。
从你所说的,听起来你有两个主要的潜在性能瓶颈。首先是插入。如果您可以让插入发生在表的末尾,这将最小化碎片并最大化吞吐量。如果它们位于表的中间,那么随着碎片的增加,性能将受到影响。
第二个领域是聚合。每当进行重要的聚合时,请注意不要导致清除所有内存中的缓冲区,以便为传入的数据腾出空间。尽量减少聚合的频率,对如何分组和计数保持聪明,尽量减少磁盘磁头的移动(或者考虑使用ssd)。
您还可以完全基于传入的数据而不是新的查询在web层进行一些累积,如果服务器在收集的数据写入db之前停机,则可能需要某种回退。
你用的是InnoDB还是Myisam?
以下是一些性能原则:
最小化从web层到db的往返行程
最小化聚合查询
尽可能减少磁盘碎片并通过在表末尾插入来最大限度地提高写入速度
优化硬件配置