存储大量日志数据的最佳方式

时间:2012-10-28 15:51:34

标签: mysql database postgresql database-design nosql

我需要有关存储统计数据的最佳方法的建议。 Django上有一个项目,它有一个包含3万个在线游戏的数据库(mysql)。

每个游戏都有三个统计参数:

  • 观看次数
  • 播放次数,
  • 喜欢的次数

现在我需要每天存储这三个参数的历史数据,所以我在考虑创建一个有五列的单个数据库:

gameid, number of views, plays, likes, date (day-month-year data). 

所以最后,每一场比赛的每一天都会记录在一行中,因此在一天内这个表将有30000行,在10天内它的大小将为300000,而在一年内它的大小将为10 950 000行。我不是DBA的大专家,但这告诉我,这很快就会成为一个性能问题。我不是说5年后会发生什么。 简单图表需要此表中收集的数据

(daily, weekly, monthly, custom range).

也许您对如何存储这些数据有更好的想法?也许noSQL在这种情况下会更合适?真的需要你的建议。

5 个答案:

答案 0 :(得分:4)

postgresql中的分区非常适合大日志。首先创建父表:

create table  game_history_log (
    gameid integer,
    views integer,
    plays integer,
    likes integer,
    log_date date
);

现在创建分区。在这种情况下,每月一个,900 k行,将是好的:

create table game_history_log_201210 (
    check (log_date between '2012-10-01' and '2012-10-31')
) inherits (game_history_log);

create table game_history_log_201211 (
    check (log_date between '2012-11-01' and '2012-11-30')
) inherits (game_history_log);

注意每个分区中的检查约束。如果您尝试插入错误的分区:

insert into game_history_log_201210 (
    gameid, views, plays, likes, log_date
) values (1, 2, 3, 4, '2012-09-30');
ERROR:  new row for relation "game_history_log_201210" violates check constraint "game_history_log_201210_log_date_check"
DETAIL:  Failing row contains (1, 2, 3, 4, 2012-09-30).

分区的一个优点是,它只会在正确的分区中进行搜索,从而大大减少搜索大小,无论有多少年的数据。这里是搜索某个日期的解释:

explain
select *
from game_history_log
where log_date = date '2012-10-02';
                                              QUERY PLAN                                              
------------------------------------------------------------------------------------------------------
 Result  (cost=0.00..30.38 rows=9 width=20)
   ->  Append  (cost=0.00..30.38 rows=9 width=20)
         ->  Seq Scan on game_history_log  (cost=0.00..0.00 rows=1 width=20)
               Filter: (log_date = '2012-10-02'::date)
         ->  Seq Scan on game_history_log_201210 game_history_log  (cost=0.00..30.38 rows=8 width=20)
               Filter: (log_date = '2012-10-02'::date)

请注意,除了父表之外,它只扫描了正确的分区。显然,您可以在分区上安装索引以避免顺序扫描。

Inheritance Partitioning

答案 1 :(得分:3)

11M行并不过分,但一般情况下编制索引并且主键的聚类更重要(在InnoDB上)。我建议(game_id,date)一个主键,以便查询有关特定游戏的所有数据是连续的行。此外,当您需要最新数据时,您可能希望保留一个单独的表格,仅列出当前排名游戏的值等。

答案 2 :(得分:1)

MySQL使用10kk数据没有性能问题。您可以按游戏ID应用分区(需要至少5.5版本)。

我有MySQL DB这样的数据,目前980kk行没有问题。

答案 3 :(得分:0)

不是保留每一行,而是保持高精度的近期数据,mdeium精度的中间数据和低精度的长期数据。这是rrdtool所采用的方法,它可能比mysql更好。

答案 4 :(得分:0)

我建议不要使用关系数据库。 由于新数据不断涌现,统计数据正在迅速发生变化。 我相信像HBase这样的smth会更合适 - 因为在这里添加新记录会更快。