我目前正在开发一个PHP应用程序(预发布)。
背景
我们的MySQL数据库中有一个表,预计会变得非常大 - 单个用户在此表中拥有250,000行并不罕见。表中的每一行都有一个金额和一个日期等等。
此外,在大多数页面上非常频繁地读取(并写入)该特定表格。鉴于每行都有一个日期,我使用GROUP BY date
来最小化MySQL给出的结果集的大小 - 同一年包含的行现在只能看作一行。
但是,典型页面仍会在1000-3000个结果之间设置结果。还有许多SUM()
被执行的地方,总计数十 - 甚至数十万行。
尝试使用MySQL
在通常的页面上,MySQL通常需要大约600-900毫秒。使用LIMIT
和偏移量并没有帮助提高性能,数据已经严格规范化,因此看起来似乎没有进一步的规范化会有所帮助。
更糟糕的是,应用程序的某些部分需要从数据库中检索10,000-15,000行。然后将结果用于PHP的计算并相应地进行格式化。鉴于此,MySQL的性能是不可接受的。
尝试使用MongoDB
我已将表格转换为MongoDB,速度更快 - 通常需要大约250毫秒来检索2,000个文档。但是,聚合管道中的$group
命令 - 需要根据它们落入的年份来聚合字段 - 减慢了速度。不幸的是,保留总数并在文档被删除/更新/插入时更新也是不可能的,因为虽然我们可以使用应用程序的某些部分的年度总计,但在其他部分,计算要求每个金额都落在具体日期。
我也考虑过Redis,虽然我认为数据的复杂性超出了Redis的设计范围。
最后一根稻草
除此之外,速度很重要。因此,绩效就是优先事项。
问题:
我现在有点陷入困境,我无法在可接受的时间内检索到如此大的结果集。似乎大多数数据存储都适用于小的检索大小 - 即使是大量的数据 - 但是我还没有找到任何从更大的表/集合中检索大量数据的东西。
答案 0 :(得分:2)
我只读了前两行,但是你正在使用聚合(GROUP BY
),然后期望它只是实时?
我会说你是数据库内部的新手,不是为了破坏你,而是试图帮助你。
MySQL和MongoDB中的group运算符都在内存中。换句话说,它采用您提供的任何数据结构,无论是索引还是文档(行),它将通过每个行/文档获取字段并对其进行分组。
这意味着您可以通过确保使用索引进行分组来加快MySQL和MongoDB的速度,但这仍然只是到目前为止,即使在MongoDB中直接工作集中存储索引(内存) )。
事实上,将LIMIT
与OFFSET
一起使用可能只会让事情进一步放慢速度。由于在写出集合MySQL之后需要再次查询以获得答案。
一旦完成它将写出结果,MySQL会将其写入结果集(此处使用的内存和IO),如果你没有设置$out
,MongoDB会回复内联,最大大小为内联输出为16MB(文档的最大大小)。
这里带走的最后一点是:聚合是可怕的
没有银弹会在这里拯救你,有些数据库会试图夸耀自己的速度等等,但事实上,大多数大型聚合器都使用了一种名为"预聚合的报告"。您可以在MongoDB文档中找到快速介绍:http://docs.mongodb.org/ecosystem/use-cases/pre-aggregated-reports/
这意味着您可以将聚合和分组的工作集中到其他可以轻松完成的过程中,从而允许您的阅读主题,即需要实时实现它的实时内容。