我们目前正在研究加速应用程序的方法,其中很大一部分与实体的列表(实际上是表格)有关。
参数和要求
该列表的参数和要求如下(我将尝试仅在此处提及相关内容):
为了使模型更清晰,请考虑以下简化实体(如JPA中)模型:
class Car {
String manufacturer;
String model;
Date dateOfProduction;
List<TyreSize> allowedTyreSizes;
Set<Date> inspectionDates;
}
请不要试图在该模型中加入太多含义,因为它只是为了说明问题(我们的数据不同而且更复杂)。
“完整”的汽车列表可能如下所示:
+==============+=======+=======+===============+=============+
| Manufacturer | Model | Prod. | Allowed Tyres | Inspections |
+==============+=======+=======+===============+=============+
| BMW | 320d |01/2016| - 225/40 R18 | - 01/07/16 |
| | | | - 225/45 R17 | - 13/12/16 |
+--------------+-------+-------+---------------+-------------+
| Toyota | Camry |09/2016| - 185/70 R13 | - 31/12/16 |
+--------------+-------+-------+---------------+-------------+
由于用户可以选择要在运行时显示的列,因此我们会动态构建必要的查询。到目前为止,这一切都很顺利。
基本问题
我们遇到的问题是涉及排序和过滤时的性能:我们当前的方法是加载排序和过滤到内存所需的所有数据,在那里进行排序和过滤,然后保留已排序的ID列表和页面在那些。我们知道这有点慢,但到目前为止,性能足以满足我们的管理。事情发生了变化,因为我们现在有更多的数据可供使用,性能要求也在提高。
因此,我们正在调查改进所有数据的排序和过滤的方法,而我们目前正在跟踪在数据库上执行此操作的方法,我仍然会问这个(侧面)问题:
目前我们正在使用Postgresql,并希望尽可能继续使用它,但如果不同的存储更适合我们,至少要检查一下。
当前的方法和问题 (在底部)
如上所述,我们目前正在尝试对数据库进行排序,过滤和分页。可以使用2个查询:一个用于获取当前页面的行ID,另一个用于实际加载这些行的数据。
由于挑战是第一个问题,我将专注于此:
AFAIK我们可以在SQL中做这样的事情(使用上面的汽车示例):
SELECT DISTINCT id FROM (
SELECT id, ... FROM car c
LEFT OUTER JOIN allowedtyresizes ats ON c.id = ats.car_id
LEFT OUTER JOIN tyresizes ts ON ts.id = ats.tyresize_id
... //additional joins if required
ORDER BY ... //apply any user-defined sorts
WHERE ... //apply any user-defined filters (or maybe put them into the joins)
)
OFFSET ... //page offset
LIMIT ... //page size
理论上,这个查询(虽然可能不完全正确)应该提供我们需要的结果,以确定要为当前页面加载哪些行。
由于我们正在使用Hibernate(5.2 atm),我们希望使用HQL或Criteria来实现这一目标。但是,似乎Hibernate不支持从上面的select语句中进行选择,因此这可能不是一种可行的方法。如果我们不得不回归原生SQL或者采用完全不同的方法,那么我们就更愿意使用现有的基础设施。
所以问题是:
答案 0 :(得分:2)
我在过去的雇主中有类似的要求,我们也注意到,在较小的数据集下,数据库能够做到这一点;然而,即使是数据库也会受到影响。
我的解决方案是介绍Hibernate Search及其与ElasticSearch的集成,以将搜索数据存储在NoSQL Lucene数据存储区中,这对于基于unicode的文本查询和排序来说绝对快速,正如您所描述的那样。
这使您可以继续使用已有的Hibernate ORM基础架构,并以最小的努力将这些附加组件烘焙到您的架构中。集成是无缝的,当然值得投资,特别是当您的数据集随着时间的推移而不断增长时。
我们正在使用数百万行,并且绝对没有性能问题。执行排序和分页的查询平均花费不到100毫秒。