比方说,我们有一个高度可配置的报告系统,该系统允许用户选择列,过滤器和排序。
所有这些配置都进入了BE,在此将其转换为SQL,然后针对DB执行,然后用户看到他的报告并可以继续使用它。但是在每个操作(如排序)上,我们仍然会建立一个查询。
转换本身需要几毫秒,但是对DB的查询执行可能需要3-5秒(如果有很多并行执行,则最多需要20秒)。
所以,我正在考虑添加某种缓存。
目前,我看到3种方式:
缓存失效将是每天几次。
您认为使速度更快的最佳方法是什么?从您的角度来看,建议的解决方案有哪些利弊?如果您可以自由选择数据库和技术(Java堆栈),该怎么办?
答案 0 :(得分:1)
好的,让我们确保我做对了。
有超过1万种不同的报告
因此预先计算和预先缓存它们没有意义,它们必须按需生成。
行中没有很多数据,只有短字符串,日期和整数。将其存储在内存中甚至保存一会儿都不花钱
因此,缓存少量数据可以引发昂贵的大型查询,这很好。
添加一个表以缓存所有结果而不进行过滤,然后根据用户请求在Java端对其进行排序/过滤。
问题是,每个报表查询很可能会具有不同的列,不同的名称,因此除非您使用JSON之类的格式,否则每个表格查询都不太适合单个表,将每个缓存的结果行存储为JSON字典...在这种情况下,即使您在JSON值内的字段上创建索引,索引编制也将是一个问题,如果您的许多报告中都有不计其数的列名,那么您也将需要不计其数的索引...
闻起来像一罐蠕虫。
为每个结果添加一张表格,但仍不包含过滤器。在这种情况下,我将可以对少得多的数据进行排序/过滤,但是会有超过1万个不同的报告,而且我认为创建1万个小表也不是一件好事。
优点::每个缓存表可以具有适当的列,数据类型和索引。只需将其截断即可轻松使缓存无效。您可以将所有缓存表设置为UNLOGGED以使其更快。而且,您可以使用以前使用的相同SQL查询对缓存结果进行所有额外的排序/过滤,因此这可能是更简单的编码选项。如果您只想获取部分结果,则分页也很不错。就将报告查询的结果复制到缓存中而言,这将是最快的选择,因为缓存已在postgres中,因此无需传输数据。您还可以将缓存存储在另一个驱动器/ SSD上。
缺点:我听说大量表的主要问题是文件系统在包含大量文件的目录上的运行速度是否减慢。不过,这在现代文件系统上不应该成为问题,而且我认为1万张表不会完全困扰postgres本身。
这可能会使对information_schema的查询变慢,并且psql中的诸如“ \ dt”之类的问题成问题,因此最好将缓存表隐藏在“缓存”模式中,以免干扰。这也将使从备份中排除它们变得更加容易。
它还将在postgres服务器上使用一些RAM来缓存高速缓存表,这取决于在线用户的数量。
我会说值得进行一些基准测试。创建一个架构,添加1万张表,看看是否有问题。
类似于第一个选项,但是LRU缓存在Java端。我们可以在内存中容纳2-3k报告结果。由于我们没有很多并行用户,而只是拥有大量报告的用户,因此通常比第一种方法要快。
那是在重新设计轮子,您必须在Java中重新实现sort / filter ...再加上缓存算法... meeeh。
不过还有其他选择:
将缓存放入另一台计算机上的另一个数据库中。这可能是一个postgres实例,或者是另一个数据库(可能需要重写一些查询)。仅当缓存在数据库上占用过多RAM时,才会变得有趣。
将缓存放入Web浏览器,然后使用javascript进行过滤/排序。根据互联网的连接速度,速度可能会更快,并且会减轻服务器的负载,但是您必须编写许多JavaScript代码。
IMO,您对大量表保持谨慎,谨慎是一件好事,但是,如果运行良好,那确实是最简单的解决方案...