我
@NamedQuery(name="CustomerMarket.findByMarketId", query="SELECT DISTINCT c.marketid FROM CustomerMarket c WHERE c.marketid LIKE :mask")
在我的类 CustomerMarket 定义中命名了查询。
我想获取 350_000 个结果中的前 1_000 个,所以我应用了 setMaxResult:
Query market = session.getNamedQuery("CustomerMarket.findByMarketId");
market.setString("mask", getMask() + "%");
market.setMaxResults(1000);
List<Object> result = market.list()
执行此查询后,我检查了 server.log 并找到了这个
select distinct customerma0_.marketid as col_0_0_
from CUSTOMER_MARKET_S customerma0_
where customerma0_.marketid like ?
我有正确的数据,前 1_000 条记录,但我想知道是否应用了 TOP 限制以及在哪里。
这个 TOP 子句是如何处理的?
- TOP 应用于 Hibernate 使用的可调用语句,这不会显示在日志中
- TOP 在从 DB 接收结果并在 Java 端过滤数据后应用
- 或者别的什么
我已经设置了 persistence.xml 和 log4j.properties 来显示几乎所有内容,但我认为没有问题,因为我有 SQL 脚本。
编辑:我在两种情况下(有和没有 setMaxResults)都对性能进行了一些测量,并得到了以下时间:
long time = System.currentTimeMillis();
market.list();
LOGGER.info("time: " + (System.currentTimeMillis() - time) + "ms");
在没有 TOP 的第一种情况下,我每次选择的平均时间消耗为 1400 毫秒。在实施 TOP 的第二种情况下,我的平均时间消耗约为 150 毫秒。
也有人对我说,这个 TOP 实现可能依赖于使用的 Hibernate 方言(我们使用的是 Sybase)。并且出现在日志中的选择与发送到数据库的选择完全相同。但是在这种情况下,将 350k 结果从结果集(或结果如何存储在 Hibernate 会话中)转换为没有任何元数据的结构 List 需要这么长时间是正常的吗?我可以想象在内部它被转换为:
**SQL generating process**
**SQL setting parameters**
ResultSet rs = executeQuery();
List<Object[]> result = new ArrayList<Object[]>(rs.getFetchSize());
int rowSize = rs.getMetaData().getColumnCount()
while (rs.next) {
Object[] row = new Object[rowSize];
for (int i = 0; i < rowSize; i++) {
row[i] = rs.getObject(i);
}
}
这似乎没有那么复杂,为什么会有这个时差。可能我很天真,因为 Hibernate 是一个具有很多特性的复杂框架。:-D