我有一个包含以下表格结构的数据库:
id | entry | log_type | user_id | created_on |
------------------------------------------------|
1 |a | error | 1 | 1433752884000|
2 |b | warn | 2 | 1433752884001|
3 |c | error | 2 | 1433752884002|
4 |d | warn | 4 | 1433752884003|
我想基于created_on字段从表中获取最后一条记录,目前我正在使用以下查询获取结果列表并使用java获取其上的最后一条记录:
select * from log_table l where l.user_id=2 and l.log_type = 'error' order by l.created_on desc;
我正在使用JPA并在.getResultList()
界面上使用Query
执行查询。一旦我得到结果列表,我会get(0)
获取所需的最后记录。
我有一个包含太多数据的大表,上面的查询执行时间太长而导致应用程序停顿。我暂时无法在现有数据上添加其他索引。除了在数据上添加索引之外,还有一种替代方法可以避免此查询停止。
我正在考虑执行以下查询,
select * from log_table l where l.user_id=2 and l.log_type = 'error' order by l.created_on desc limit 1;
目前我无法对数据库执行第二次查询,因为它可能导致我的应用程序停止。第二个查询的执行是否会比第一个查询更快?
我没有足够大的数据集来重现我本地系统上的停滞问题,因此。我尝试在我的本地数据库上执行查询,并且由于缺少可用的大数据集,无法确定第二个查询是否会更快添加" limit
"在返回的查询上。
如果上面的第二个查询不能提供更好的结果,那么我应该采用什么方法来获得优化的查询。
如果第二个查询应该足够好以避免停止,是不是因为DB只提取一个记录而不是整个记录集?与查看/获取太多记录(如在第一个查询中)相比,数据库处理单个记录的查找/获取方式不同,以改进查询计时。
答案 0 :(得分:0)
在执行query.getResultList()
之前,您需要query.setMaxResults(1)
。这相当于LIMIT 1
。
但请注意,如果您的实体在查询中有一个与其关联的相关子对象的集合,则实体管理器可能仍然必须执行无界选择以获取构建第一个实体所需的所有数据。有关详细信息,请参阅this question and answer。
在您的情况下,由于您只需要一个实体,我建议您在完成初始查询后延迟加载任何附加的实体。
答案 1 :(得分:0)
表现取决于......
ORDER BY x LIMIT 1
是一种常见的模式。它可能也可能不是非常有效 - 它取决于查询和索引。
在你的情况下:
where l.user_id=2 and l.log_type = 'error' order by l.created_on desc
这将是最佳的:
INDEX(user_id, log_type, created_on)
使用该索引,它基本上会进行一次探测以找到您需要的行。如果没有该索引,它将扫描表的大部分或全部,按降序排序(ORDER BY .. DESC
)并传递第一行(LIMIT 1
)