【问题标题】:Is it performative to use criteria.list () to determine the number of rows returned?使用criteria.list() 确定返回的行数是否具有执行性?
【发布时间】:2017-03-07 23:08:13
【问题描述】:

我有一个 Criteria 对象,用于获取通用列表。但在特定情况下,我想使用相同的 Criteria 对象来仅了解返回的行数。

我的问题是我是否使用:

Integer count = criteria.list().size();

与以下内容相同:

criteria.setProjection(Projections.rowCount());
Integet count = (Integer)criteria.uniqueResult()

【问题讨论】:

  • 在您真正注意到您的代码运行缓慢之前,尽量不要担心性能问题。大多数时候,像这样的小事情并不重要,您需要修复的事情无论如何都会出现在您没想到的地方。
  • 大部分同意@nhouser9,但如果可行,这是您应该使用内置计数方法的一个领域。这是一个可读性很强的优化,它在服务器端折叠数据。

标签: java sql hibernate criteria


【解决方案1】:

在几乎所有情况下,您的投影通常会胜过list().size() 方法调用。为了理解原因,我们需要强调两种方法之间的差异。

当您要求 Hibernate 执行 list().size() 时,会发生什么?

  1. 我们在数据库级别向目标表发出选择。
  2. 数据库必须从磁盘读取数据页,将结果加载到内存中。这会消耗宝贵的数据库服务器资源,例如 CPU 周期、磁盘 i/o 和内存。
  3. 数据库服务器必须将这些结果流式传输到应用程序服务器。此过程受结果集的行数、宽度和网络连接延迟的影响很大。
  4. 在应用服务器上实例化集合元素并将每个构造的实例添加到 Hibernate Session 的持久性上下文(1LC)。这再次消耗内存和 CPU 周期来实例化和存储这些对象。
  5. 如果您的集合元素包含任何急切加载的关联,那么 Hibernate 将再次重复步骤 1 到 4,直到基于获取模式加载对象图。显然,当您所追求的只是集合元素的计数时,这完全没有必要。
  6. 让 JVM 给你一个收集计数,虽然很小但仍然浪费了 cpu 周期。

当您要求 Hibernate 执行 Projection.rowCount() 时,会发生什么?

  1. 我们在数据库级别向目标表发出投影查询。
  2. 而不是数据库需要从磁盘读取数据页,如果您的 projectin 查询只是基于主键和任何索引条件进行计数,则查询将快速返回,无论我们是在谈论小型还是行的大表。
  3. 与其将多行多列的结果集流式传输回应用程序服务器,返回的只是一个值,即计数。这几乎不会消耗任何网络带宽。
  4. 由于我们返回单个值,Hibernate 几乎不会返回该值。此外,由于它是一个聚合值,我们不会将任何信息放入 Session 的持久化上下文(1LC)中,因此这里没有不必要的内存消耗。
  5. 由于我们没有返回实体,因此不会加载任何关联。
  6. JVM 不需要计算任何东西,JDBC 结果就是计数。

TLDR:

投影将在数据库服务器和应用程序服务器级别使用更少的 CPU、内存和磁盘 i/o,并且不会受到网络延迟的影响,因为结果是单个值,而不像较大的结果集可能.

虽然我知道人们更喜欢过早地优化,但我确实认为重要的是,当我们需要某个资源中的某些东西时,我们实际上要求该资源准确地为我们提供我们想要的东西,而不是尝试间接获得想要的结果。这几乎总是技术债务,您必须稍后再回来修复。

【讨论】:

  • 哇,真是一颗被低估的珍珠。感谢您的专家见解!
猜你喜欢
  • 1970-01-01
  • 2022-01-23
  • 2015-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 2016-02-27
相关资源
最近更新 更多