【发布时间】:2021-04-23 13:43:51
【问题描述】:
我有以下示例查询,它在
Query qry = em.createQuery(
"select e from Example e where e.ids in :ids ")
.setParameter("ids", ids); // List<String> ids
由于列表可以为 null 或为空,我包含了以下在数据库端同样快速终止的简单条件检查:
Query qry = em.createQuery(
"select e from Example e where (:idFilterUsed = false OR e.ids in :ids ) ")
.setParameter("ids", ids) // List<String>
.setParameter("idFilterUsed", idFilterUsed); // boolean
即使较低的查询似乎只有一个小的琐碎条件,查询和映射也需要 12 到 20 秒,而不是
我无法解释我已经做了什么,什么没有帮助我:
- 使用 .createNativeQuery 并在 Example.class 中解析结果
- 使用整数 (0/1) 而不是布尔参数
- 在 OR 条件内更改顺序
任何人都知道它可能是什么,或者如果存在条件,是否有替代方法可以抛出此类 IN 查询?我的许多查询都需要几个这样的条件检查。
查询在 Oracle 12g 数据库上运行,我使用 Hibernate 5.4.27。
编辑:为了避免误解 -> 如果输入列表 (ids) 填充了至少一个 ID 和 idFilterUser = true,则查询具有这种极端的性能损失。当列表为空时,查询速度很慢是合乎逻辑的,但实际上这并没有影响,因为它附加了更多的条件。
【问题讨论】:
-
性能不好是因为如果id列表为空,你会加载一个表的所有内容,所以数据库必须进行全表扫描并通过网络传输所有数据所以然后 Hibernate 可以从中实现对象。您应该限制要获取的数据量,例如
.setMaxResults(10) -
嘿克里斯蒂安,谢谢您的回复。如果 id 列表为空,则 idFilterUsed 设计为 false。 OR 条件不会在 IN 语句之前终止吗?在数据库方面似乎是这样,至少查询时间告诉我。
-
正确的
idFilterUsed是false,因此查询会返回所有行。这就是性能不佳的原因。 -
你是对的,但我也遇到了问题,当
idFilterUsed = true(并且 :ids 甚至填充了一个(!)单个 id )时,这对我来说根本没有意义。我描述的问题与使用 Hibernate 和在数据库本身上返回很少结果(行大小 -
我猜你缺少一个索引,当你尝试通过 SQL 编辑器执行它时,你很幸运,数据仍在数据库的页面缓存中,所以速度更快。