我已命名查询
@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子句是如何处理的?
我已经设置了persistance.xml和log4j.properties来显示几乎所有东西,但我认为没有问题,因为我有SQL脚本。
修改: 我在两种情况下(使用和不使用setMaxResults)对性能进行了一些测量,并得到以下时间:
long time = System.currentTimeMillis();
market.list();
LOGGER.info("time: " + (System.currentTimeMillis() - time) + "ms");
在没有TOP的第一种情况下,我每次选择的平均时间消耗为1400ms。 在实施TOP的第二种情况下,我的平均时间消耗约为150ms。
我还告诉我,这个TOP实现可能依赖于使用过的Hibernate方言(我们使用的是Sybase)。并且日志中显示的选择与发送到DB完全相同。 但是在这种情况下将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
答案 0 :(得分:0)
似乎我的问题在于我用于我的应用程序的数据库。在链接www.petefreitag.com/item/59.cfm上,描述了用户如何限制其结果数量。如您所见,Sybase中只有一种选择分为两个单独的动作(SET + SELECT)。所以整个问题是没有记录第一个动作而第二个动作是。