【问题标题】:Efficient way to get last record from the database从数据库中获取最后一条记录的有效方法
【发布时间】:2015-06-08 09:32:36
【问题描述】:

我有一个具有以下表结构的数据库:

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,我在 Query 接口上使用 .getResultList() 执行查询。一旦我得到结果列表,我会执行 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”后第二个查询是否会更快。

如果上述第二个查询不应该提供更好的结果,我应该采用什么方法来获得优化的查询。

如果第二个查询应该足够好以避免停滞,是因为数据库只获取一条记录而不是整个记录集的原因吗?与查找/获取太多记录(如在第一次查询中)相比,数据库处理查找/获取单个记录的方式是否不同以改善查询时间。

【问题讨论】:

标签: mysql database jpa query-optimization


【解决方案1】:

性能取决于...

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)

【讨论】:

    【解决方案2】:

    在你做你的query.getResultList()之前,你需要query.setMaxResults(1)。这相当于LIMIT 1

    但请注意,如果您的实体在查询中加入了相关子对象的集合,实体管理器可能仍需要进行无限选择以获取构建第一个实体所需的所有数据。有关详细信息,请参阅this question and answer

    在您的情况下,由于您只需要一个实体,我建议您在完成初始查询后延迟加载任何附加的实体。

    【讨论】:

      猜你喜欢
      • 2016-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-02
      • 1970-01-01
      • 1970-01-01
      • 2011-10-26
      • 1970-01-01
      相关资源
      最近更新 更多