我们的eshop中有大约170万种产品,我们希望记录该产品长达1年的观看次数,我们希望每隔至少2小时记录一次观点,问题是用什么结构这个任务?
现在我们尝试将统计信息保留30天,记录中有2列classified_id,stats
,其中统计信息就像是带有格式日期的剥离json:views,date:views ...例如记录看起来像
345422,{051216:23212,051217:64233} where 051216,051217=mm/dd/yy and 23212,64233=number of views
如果你想要回归1年,这当然有点愚蠢,因为如果你想获得1000个产品的视图总和,你需要从数据库中获取30mb,并自己计算。
我们现在想到的另一种方式就是拥有一个包含3列classified_id,date,view
的大型表,并将其记录存储在自己的行中,这当然会产生一个巨大的表,其中包含数亿个行,例如,如果我们有180万个分类广告,并且我们需要每2小时一年24小时保存记录
1800000 * 365 * 12 = 7.884.000.000(数十亿有B)行虽然它在postgres的理论极限内,我想象它上面的查询(比如更新视图),即使有正确的索引,将需要一些时间。
有什么建议吗?我甚至无法想象谷歌分析如何存储统计数据......
答案 0 :(得分:2)
这个数字并不像你想象的那么高。在目前的工作中,我们存储网站的指标数据,我们拥有的总行数要高得多。在之前的工作中,我与pg数据库合作,该数据库从移动网络收集指标,每天收集约20亿条记录。所以不要害怕数十亿的记录。
您肯定需要对数据进行分区 - 最有可能是白天。有了这么多的数据,您就会发现索引毫无用处。取决于您将在EXPLAIN
命令输出中看到的平面。例如,电信公司应用程序根本不使用任何索引,因为它们只会减慢整个引擎的速度。
另一个问题是您需要快速回复查询。对于允许用户进行查询的粒度(小时数/天/周等)的步骤。您甚至可能需要针对粒度(如周,月或季度)进行一些汇总。
增加:
该电信应用每天约有20亿条记录每天耗费约290GB。它意味着使用带有COPY命令的批量插入每秒插入约23000条记录。每个批量都有数千条记录。原始数据按分钟划分。为了避免磁盘等待,db在4个不同的磁盘/阵列上有4个表空间,并且分区分布在它们上面。 PostreSQL能够毫无问题地处理它。所以你也应该考虑正确的硬件配置。
好主意也是将pg_xlog目录移动到单独的磁盘或阵列。不只是不同的文件系统。这一切都必须是单独的硬件。 SSD我只能在具有正确错误检查的阵列中推荐。最近我们在单个SSD上遇到了数据库损坏的问题。
答案 1 :(得分:1)
首先,不要使用数据库记录统计信息。或者,至少使用不同的数据库。日志的写入开销会降低Web应用程序的响应速度。而且你的日常备份需要更长的时间,因为大表不需要经常备份。
"自己做"我选择的解决方案是异步写入日志文件,然后处理这些文件以构建分析数据库中的统计信息。 this response中有异步写入的良好代码片段。或者,您可以对可用于Java的许多记录器进行基准测试。
另请注意,Apache Kafka等产品专门用于收集此类信息。
另一种可能性是在面向列的数据库(如HBase或Cassandra)中创建时间序列。在这种情况下,每个产品只有一行,列数与列数一样多。
最后,如果要对数据库执行此操作,就像@JosMac指出的那样,创建分区,尽可能避免使用索引。将fillfactor存储参数设置为100.您还可以考虑UNLOGGED表。但在关闭预写日志之前,请仔细阅读PostgreSQL文档。
答案 2 :(得分:1)
只是为您提出另一个非RDBMS选项(所以有点偏离主题),您可以将文本文件(CSV,TSV,JSON,Parquet,ORC)发送到Amazon S3并使用AWS Athena直接使用SQL查询它
由于它将查询自由文本文件,您可以只发送未经过滤的weblog,并通过JDBC查询它们。