哪种数据存储最适合我的情况?


10

我正在开发一个涉及数据库中更新/选择查询执行非常高的应用程序。

我有一个基本表(A),该表每天将有一个实体约500条记录。对于系统中的每个用户,将根据用户的某些首选项创建此实体的变体,并将它们存储在另一个表(B)中。这是通过每天在午夜运行的Cron作业完成的。

因此,如果表A中有10,000个用户和500条记录,则该天表B中将有500万条记录。我总是将数据保留在这些表中一天,午夜将历史数据存档到HBase。此设置运行良好,到目前为止,我没有任何性能问题。

最近业务需求发生了一些变化,现在基本表A中的某些属性(对于15-20条记录)将每20秒更改一次,因此我必须重新计算表B中所有这些变化记录的某些值,全部用户。即使仅更改20条主记录,我也需要重新计算并更新200,000条用户记录,这花费了20秒钟以上的时间,然后才发生下一次更新,最终导致所有Select查询排队。我从在线用户那里得到3个获取请求/ 5秒,这导致6-9个选择查询。为了响应api请求,我总是使用表B中的字段。

我可以购买更多的处理能力来解决这种情况,但是我对拥有一个可以处理甚至一百万用户的适当缩放的系统感兴趣。

这里有人可以提出更好的选择吗?Nosql +关系数据库对我有帮助吗?是否有任何平台/数据存储可让我频繁地更新数据而不会锁定,同时又使我能够灵活地在实体的各个字段上运行选择查询?


您真的需要存储所有这些数据吗?这听起来似乎有点像您最好根据要求进行计算。如果您可以在20秒多一点的时间内计算出200k条记录,那么应该有可能立即计算出这20条记录* 3个用户= 60条记录。可能您可以查看哪些用户何时在线,并进行更多优化?看起来有点像您正在生成大量从未使用过的数据(至少在数据仍然有效期间)
thorstenmüller2015年

仅为登录用户生成是一个很好的选择。我也曾考虑过这一点,但仍然不是一种可扩展的方法。我的平台仅在白天使用,因此在此期间,大多数用户将处于活动状态。还有其他建议吗?
水罐2015年

@Jugs-剩下的问题是您是否可以即时进行计算。您是否需要更新记录,还是您的应用程序只需要数据就可以了?
Bobson

恐怕我无法即时进行计算,因为条目表B是为用户(5星到1星)排名的,在完成这些计算之后,我们将再次为该用户排名。用户的整个过程需要500毫秒,如果我即时进行操作,则会影响我们的API响应时间
Jugs 2015年

我在想是否将分数和排名存储在RDBMS之外是否有意义,可能是在nosql db中,以便select语句仍然可以正常运行,但是有时我也需要查询分数和排名。所以我现在有点迷失,这就是为什么我向像你们一样的专家寻求建议的原因
Jugs 2015年

Answers:


1

看起来该表B是某种缓存。但是这种缓存会降低生产率。

即使您每秒有25个查询,您也可以拒绝使用表B,并为每个请求计算答案。

无论如何,如果您在更新20条记录时有30秒的延迟-这在软件体系结构中是失败的(我错了,如果您的数据库为每条记录计算PI的前10 ^ 100个标志)。

据我所知,没有丑陋的SQL查询,具有索引且记录少于1000000条的关系数据库几乎可以完美地适用于所有查询。

尝试拒绝使用表,B并向表中添加适当的索引A(大多数现代数据库都具有辅助工具)。下一步:尝试优化数据(表A)和查询的结构(使用查询分析器或SQL专家)以加快计算速度。如果您将更新仅20记录-索引的存在不会伤害一个生产力更新的过程,但显著提高选择速度。


1

问题实际上是什么系统计算要插入到B中的记录以及B数据的大小。

假设对象不大,任何数据库(例如MSSQL)都应该能够处理您正在谈论的插入量。

更新可能会遇到更困难的问题,但是使用正确的索引和锁定,同样也不会成为大问题。

99%的时间,我看到这样的问题是由于B记录是由存储的proc计算出来的。这将所有负载放在数据库服务器上

如果是这种情况,解决方案是将代码移至可通过排队系统调用的脱机服务。

因此,您的更新A消息将触发工作进程,该工作进程将遍历用户并为每个用户创建更新B消息

第二个工作进程B将使用数据A更新更新用户X,并创建B记录并更新数据库。

可以通过添加更多具有队列工作器的框来进行扩展,因此您在计算后拥有越来越多的处理能力,而您的数据库则可以自由地专注于更新和选择。

您可以通过将选择与更新/插入分开来进一步优化。具有一个新数据库,该数据库将所有选择请求作为复制从属,而旧数据库则获得所有更新。


0

如果您在Amazon中运行,我会考虑DynamoDB。它基于闪存。这是它的链接:https : //aws.amazon.com/dynamodb/

您正在使用哪种RDBMS?您可能可以通过使用UDF或视图中的计算字段来提高性能。您是通过单个更新查询在数据库中运行计算,还是从数据库中选择数据,在另一个进程中运行计算然后将其加载回?

默认情况下,Oracle被配置为使用快照模式执行,这意味着在更新期间行不会被锁定,并且并发选择会获得原始值。默认情况下,SQL Server配置为悲观并发,因此并发选择将一直阻塞,直到更新完成。某些版本的SQL Server可以置于快照模式,但是,这大大增加了临时表的压力。

您正在哪种环境中运行?如果它是Amazon EC2实例上的RDBMS,则尝试将数据库数据文件放在本地闪存磁盘上。在将文件从EBS移到本地磁盘时,我已经看到一个数量级的差异。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.